3047d5b880188db0d041b161b1b108d49460f8be
[reactos.git] / reactos / lib / drivers / oskittcp / oskittcp / interface.c
1 #include <oskittcp.h>
2 #include <oskitdebug.h>
3 #include <net/raw_cb.h>
4
5 #include <sys/param.h>
6 #include <sys/systm.h>
7 #include <sys/socket.h>
8 #include <sys/kernel.h>
9 #include <sys/filedesc.h>
10 #include <sys/proc.h>
11 #include <sys/fcntl.h>
12 #include <sys/file.h>
13 #include <sys/mbuf.h>
14 #include <sys/protosw.h>
15 #include <sys/socket.h>
16 #include <sys/socketvar.h>
17 #include <sys/uio.h>
18
19 struct linker_set domain_set;
20
21 OSKITTCP_EVENT_HANDLERS OtcpEvent = { 0 };
22
23 //OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA;
24 OSK_UINT OskitDebugTraceLevel = 0;
25
26 /* SPL */
27 unsigned cpl;
28 unsigned net_imask;
29 unsigned volatile ipending;
30 struct timeval boottime;
31
32 void clock_init();
33 int _snprintf(char * buf, size_t cnt, const char *fmt, ...);
34
35 void *fbsd_malloc( unsigned int bytes, char *file, unsigned line, ... ) {
36 if( !OtcpEvent.TCPMalloc ) panic("no malloc");
37 return OtcpEvent.TCPMalloc
38 ( OtcpEvent.ClientData, (OSK_UINT)bytes, (OSK_PCHAR)file, line );
39 }
40
41 void fbsd_free( void *data, char *file, unsigned line, ... ) {
42 if( !OtcpEvent.TCPFree ) panic("no free");
43 OtcpEvent.TCPFree( OtcpEvent.ClientData, data, (OSK_PCHAR)file, line );
44 }
45
46 void InitOskitTCP() {
47 OS_DbgPrint(OSK_MID_TRACE,("Init Called\n"));
48 OS_DbgPrint(OSK_MID_TRACE,("MB Init\n"));
49 mbinit();
50 OS_DbgPrint(OSK_MID_TRACE,("Rawip Init\n"));
51 rip_init();
52 raw_init();
53 OS_DbgPrint(OSK_MID_TRACE,("Route Init\n"));
54 route_init();
55 OS_DbgPrint(OSK_MID_TRACE,("Init clock\n"));
56 clock_init();
57 OS_DbgPrint(OSK_MID_TRACE,("Init TCP\n"));
58 tcp_init();
59 OS_DbgPrint(OSK_MID_TRACE,("Init routing\n"));
60 domaininit();
61 OS_DbgPrint(OSK_MID_TRACE,("Init Finished\n"));
62 tcp_iss = 1024;
63 }
64
65 void DeinitOskitTCP() {
66 }
67
68 void TimerOskitTCP( int FastTimer, int SlowTimer ) {
69 if ( SlowTimer ) {
70 tcp_slowtimo();
71 }
72 if ( FastTimer ) {
73 tcp_fasttimo();
74 }
75 }
76
77 void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
78 memcpy( &OtcpEvent, EventHandlers, sizeof(OtcpEvent) );
79 }
80
81 void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len )
82 {
83 unsigned int i;
84 char line[81];
85 static const char* hex = "0123456789abcdef";
86
87 for ( i = 0; i < Len; i++ )
88 {
89 int align = i & 0xf;
90 int align3 = (align<<1) + align;
91 unsigned char c = Data[i];
92 if ( !align )
93 {
94 if ( i ) DbgPrint( line );
95 _snprintf ( line, sizeof(line)-1, "%08x: \n", &Data[i] );
96 line[sizeof(line)-1] = '\0';
97 }
98
99 line[10+align3] = hex[(c>>4)&0xf];
100 line[11+align3] = hex[c&0xf];
101 if ( !isprint(c) )
102 c = '.';
103 line[59+align] = c;
104 }
105 if ( Len & 0xf )
106 DbgPrint ( line );
107 }
108
109 /* From uipc_syscalls.c */
110
111 int OskitTCPSocket( void *context,
112 void **aso,
113 int domain,
114 int type,
115 int proto )
116 {
117 struct socket *so;
118 int error = socreate(domain, &so, type, proto);
119 if( !error ) {
120 so->so_connection = context;
121 so->so_state |= SS_NBIO;
122 *aso = so;
123 }
124 return error;
125 }
126
127 int OskitTCPRecv( void *connection,
128 OSK_PCHAR Data,
129 OSK_UINT Len,
130 OSK_UINT *OutLen,
131 OSK_UINT Flags ) {
132 struct uio uio = { 0 };
133 struct iovec iov = { 0 };
134 int error = 0;
135 int tcp_flags = 0;
136
137 OS_DbgPrint(OSK_MID_TRACE,
138 ("so->so_state %x\n", ((struct socket *)connection)->so_state));
139
140 if( Flags & OSK_MSG_OOB ) tcp_flags |= MSG_OOB;
141 if( Flags & OSK_MSG_DONTWAIT ) tcp_flags |= MSG_DONTWAIT;
142 if( Flags & OSK_MSG_PEEK ) tcp_flags |= MSG_PEEK;
143
144 iov.iov_len = Len;
145 iov.iov_base = (char *)Data;
146 uio.uio_iov = &iov;
147 uio.uio_iovcnt = 1;
148 uio.uio_offset = 0;
149 uio.uio_resid = Len;
150 uio.uio_segflg = UIO_SYSSPACE;
151 uio.uio_rw = UIO_READ;
152 uio.uio_procp = NULL;
153
154 OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len));
155
156 error = soreceive( connection, NULL, &uio, NULL, NULL /* SCM_RIGHTS */,
157 &tcp_flags );
158 *OutLen = Len - uio.uio_resid;
159
160 return error;
161 }
162
163 int OskitTCPBind( void *socket,
164 void *nam, OSK_UINT namelen ) {
165 int error = EFAULT;
166 struct socket *so = socket;
167 struct mbuf sabuf;
168 struct sockaddr addr;
169
170 OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
171
172 if (!socket)
173 return OSK_ESHUTDOWN;
174
175 if( nam )
176 addr = *((struct sockaddr *)nam);
177
178 RtlZeroMemory(&sabuf, sizeof(sabuf));
179 sabuf.m_data = (void *)&addr;
180 sabuf.m_len = sizeof(addr);
181
182 addr.sa_family = addr.sa_len;
183 addr.sa_len = sizeof(struct sockaddr);
184
185 error = sobind(so, &sabuf);
186
187 OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
188 return (error);
189 }
190
191 int OskitTCPConnect( void *socket, void *connection,
192 void *nam, OSK_UINT namelen ) {
193 struct socket *so = socket;
194 int error = EFAULT;
195 struct mbuf sabuf;
196 struct sockaddr addr;
197
198 OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
199
200 so->so_connection = connection;
201
202 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
203 error = EALREADY;
204 goto done;
205 }
206
207 OS_DbgPrint(OSK_MIN_TRACE,("Nam: %x\n", nam));
208 if( nam )
209 addr = *((struct sockaddr *)nam);
210
211 RtlZeroMemory(&sabuf, sizeof(sabuf));
212 sabuf.m_data = (void *)&addr;
213 sabuf.m_len = sizeof(addr);
214
215 addr.sa_family = addr.sa_len;
216 addr.sa_len = sizeof(struct sockaddr);
217
218 error = soconnect(so, &sabuf);
219
220 if (error)
221 goto bad;
222
223 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
224 error = EINPROGRESS;
225 goto done;
226 }
227
228 bad:
229 so->so_state &= ~SS_ISCONNECTING;
230
231 if (error == ERESTART)
232 error = EINTR;
233
234 done:
235 OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
236 return (error);
237 }
238
239 int OskitTCPShutdown( void *socket, int disconn_type ) {
240 if (!socket)
241 return OSK_ESHUTDOWN;
242
243 return soshutdown( socket, disconn_type );
244 }
245
246 int OskitTCPClose( void *socket ) {
247 struct socket *so = socket;
248
249 if (!socket)
250 return OSK_ESHUTDOWN;
251
252 so->so_connection = 0;
253 soclose( so );
254 return 0;
255 }
256
257 int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
258 OSK_UINT *OutLen, OSK_UINT flags ) {
259 int error;
260 struct uio uio;
261 struct iovec iov;
262
263 if (!socket)
264 return OSK_ESHUTDOWN;
265
266 iov.iov_len = Len;
267 iov.iov_base = (char *)Data;
268 uio.uio_iov = &iov;
269 uio.uio_iovcnt = 1;
270 uio.uio_offset = 0;
271 uio.uio_resid = Len;
272 uio.uio_segflg = UIO_SYSSPACE;
273 uio.uio_rw = UIO_WRITE;
274 uio.uio_procp = NULL;
275
276 error = sosend( socket, NULL, &uio, NULL, NULL, 0 );
277 *OutLen = Len - uio.uio_resid;
278
279 return error;
280 }
281
282 int OskitTCPAccept( void *socket,
283 void **new_socket,
284 void *AddrOut,
285 OSK_UINT AddrLen,
286 OSK_UINT *OutAddrLen,
287 OSK_UINT FinishAccepting ) {
288 struct socket *head = (void *)socket;
289 struct sockaddr *name = (struct sockaddr *)AddrOut;
290 struct socket **newso = (struct socket **)new_socket;
291 struct socket *so = socket;
292 struct sockaddr_in sa;
293 struct mbuf mnam;
294 struct inpcb *inp;
295 int namelen = 0, error = 0, s;
296
297 if (!socket)
298 return OSK_ESHUTDOWN;
299
300 if (!new_socket || !AddrOut)
301 return OSK_EINVAL;
302
303 OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Doing accept (Finish %d)\n",
304 FinishAccepting));
305
306 *OutAddrLen = AddrLen;
307
308 if (name)
309 /* that's a copyin actually */
310 namelen = *OutAddrLen;
311
312 s = splnet();
313
314 #if 0
315 if ((head->so_options & SO_ACCEPTCONN) == 0) {
316 splx(s);
317 OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: head->so_options = %x, wanted bit %x\n",
318 head->so_options, SO_ACCEPTCONN));
319 error = EINVAL;
320 goto out;
321 }
322 #endif
323
324 OS_DbgPrint(OSK_MID_TRACE,("head->so_q = %x, head->so_state = %x\n",
325 head->so_q, head->so_state));
326
327 if ((head->so_state & SS_NBIO) && head->so_q == NULL) {
328 splx(s);
329 error = EWOULDBLOCK;
330 goto out;
331 }
332
333 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
334 while (head->so_q == NULL && head->so_error == 0) {
335 if (head->so_state & SS_CANTRCVMORE) {
336 head->so_error = ECONNABORTED;
337 break;
338 }
339 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
340 error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH,
341 "accept", 0);
342 if (error) {
343 splx(s);
344 goto out;
345 }
346 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
347 }
348 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
349
350 #if 0
351 if (head->so_error) {
352 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
353 error = head->so_error;
354 head->so_error = 0;
355 splx(s);
356 goto out;
357 }
358 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
359 #endif
360
361 /*
362 * At this point we know that there is at least one connection
363 * ready to be accepted. Remove it from the queue.
364 */
365 so = head->so_q;
366
367 inp = so ? (struct inpcb *)so->so_pcb : NULL;
368 if( inp && name ) {
369 ((struct sockaddr_in *)AddrOut)->sin_addr.s_addr =
370 inp->inp_faddr.s_addr;
371 ((struct sockaddr_in *)AddrOut)->sin_port = inp->inp_fport;
372 }
373
374 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
375 if( FinishAccepting && so ) {
376 head->so_q = so->so_q;
377 head->so_qlen--;
378
379 *newso = so;
380
381 /*so->so_state &= ~SS_COMP;*/
382
383 mnam.m_data = (char *)&sa;
384 mnam.m_len = sizeof(sa);
385
386 (void) soaccept(so, &mnam);
387
388 so->so_state = SS_NBIO | SS_ISCONNECTED;
389 so->so_q = so->so_q0 = NULL;
390 so->so_qlen = 0;
391 so->so_head = 0;
392
393 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
394 if (name) {
395 /* check sa_len before it is destroyed */
396 memcpy( AddrOut, &sa, AddrLen < sizeof(sa) ? AddrLen : sizeof(sa) );
397 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
398 *OutAddrLen = namelen; /* copyout actually */
399 }
400 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
401 splx(s);
402 }
403 out:
404 OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Returning %d\n", error));
405 return (error);
406 }
407
408 /* The story so far
409 *
410 * We have a packet. While we store the fields we want in host byte order
411 * outside the original packet, the bsd stack modifies them in place.
412 */
413
414 void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
415 OSK_UINT IpHeaderLen ) {
416 struct mbuf *Ip = m_devget( (char *)Data, Len, 0, NULL, NULL );
417 struct ip *iph;
418
419 if( !Ip ) return; /* drop the segment */
420
421 //memcpy( Ip->m_data, Data, Len );
422 Ip->m_pkthdr.len = IpHeaderLen;
423
424 /* Do the transformations on the header that tcp_input expects */
425 iph = mtod(Ip, struct ip *);
426 NTOHS(iph->ip_len);
427 iph->ip_len -= sizeof(struct ip);
428
429 OS_DbgPrint(OSK_MAX_TRACE,
430 ("OskitTCPReceiveDatagram: %d (%d header) Bytes\n", Len,
431 IpHeaderLen));
432
433 tcp_input(Ip, IpHeaderLen);
434
435 /* The buffer Ip is freed by tcp_input */
436 }
437
438 int OskitTCPSetSockOpt(void *socket,
439 int level,
440 int optname,
441 char *buffer,
442 int size)
443 {
444 struct mbuf *m;
445
446 if (!socket)
447 return OSK_ESHUTDOWN;
448
449 if (size >= MLEN)
450 return OSK_EINVAL;
451
452 m = m_get(M_WAIT, MT_SOOPTS);
453 if (!m)
454 return OSK_ENOMEM;
455
456 m->m_len = size;
457
458 memcpy(m->m_data, buffer, size);
459
460 /* m is freed by sosetopt */
461 return sosetopt(socket, level, optname, m);
462 }
463
464 int OskitTCPGetSockOpt(void *socket,
465 int level,
466 int optname,
467 char *buffer,
468 int *size)
469 {
470 int error, oldsize = *size;
471 struct mbuf *m;
472
473 if (!socket)
474 return OSK_ESHUTDOWN;
475
476 error = sogetopt(socket, level, optname, &m);
477 if (!error)
478 {
479 *size = m->m_len;
480
481 if (!buffer || oldsize < m->m_len)
482 {
483 m_freem(m);
484 return OSK_EINVAL;
485 }
486
487 memcpy(buffer, m->m_data, m->m_len);
488
489 m_freem(m);
490 }
491
492 return error;
493 }
494
495 int OskitTCPListen( void *socket, int backlog ) {
496 int error;
497
498 if (!socket)
499 return OSK_ESHUTDOWN;
500
501 OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
502 error = solisten( socket, backlog );
503 OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
504
505 return error;
506 }
507
508 int OskitTCPSetAddress( void *socket,
509 OSK_UINT LocalAddress,
510 OSK_UI16 LocalPort,
511 OSK_UINT RemoteAddress,
512 OSK_UI16 RemotePort ) {
513 struct socket *so = socket;
514 struct inpcb *inp;
515
516 if (!socket)
517 return OSK_ESHUTDOWN;
518
519 inp = (struct inpcb *)so->so_pcb;
520 inp->inp_laddr.s_addr = LocalAddress;
521 inp->inp_lport = LocalPort;
522 inp->inp_faddr.s_addr = RemoteAddress;
523 inp->inp_fport = RemotePort;
524
525 return 0;
526 }
527
528 int OskitTCPGetAddress( void *socket,
529 OSK_UINT *LocalAddress,
530 OSK_UI16 *LocalPort,
531 OSK_UINT *RemoteAddress,
532 OSK_UI16 *RemotePort ) {
533 struct socket *so = socket;
534 struct inpcb *inp;
535
536 if (!socket)
537 return OSK_ESHUTDOWN;
538
539 inp = (struct inpcb *)so->so_pcb;
540 *LocalAddress = inp->inp_laddr.s_addr;
541 *LocalPort = inp->inp_lport;
542 *RemoteAddress = inp->inp_faddr.s_addr;
543 *RemotePort = inp->inp_fport;
544
545 return 0;
546 }
547
548 struct ifaddr *ifa_iffind(struct sockaddr *addr, int type)
549 {
550 if( OtcpEvent.FindInterface )
551 return OtcpEvent.FindInterface( OtcpEvent.ClientData,
552 PF_INET,
553 type,
554 addr );
555 else
556 return NULL;
557 }
558
559 void oskittcp_die( const char *file, int line ) {
560 DbgPrint("\n\n*** OSKITTCP: Panic Called at %s:%d ***\n", file, line);
561 *((int *)0) = 0;
562 }
563
564 /* Stuff supporting the BSD network-interface interface */
565 struct ifaddr **ifnet_addrs;
566 struct ifnet *ifnet;
567
568 void
569 ifinit()
570 {
571 }
572
573
574 void
575 if_attach(ifp)
576 struct ifnet *ifp;
577 {
578 panic("if_attach\n");
579 }
580
581 struct ifnet *
582 ifunit(char *name)
583 {
584 return 0;
585 }
586
587 /*
588 * Handle interface watchdog timer routines. Called
589 * from softclock, we decrement timers (if set) and
590 * call the appropriate interface routine on expiration.
591 */
592 void
593 if_slowtimo(arg)
594 void *arg;
595 {
596 #if 0
597 register struct ifnet *ifp;
598 int s = splimp();
599
600 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
601 if (ifp->if_timer == 0 || --ifp->if_timer)
602 continue;
603 if (ifp->if_watchdog)
604 (*ifp->if_watchdog)(ifp->if_unit);
605 }
606 splx(s);
607 timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
608 #endif
609 }
610
611 /*
612 * Locate an interface based on a complete address.
613 */
614
615 /*ARGSUSED*/
616 struct ifaddr *ifa_ifwithaddr(addr)
617 struct sockaddr *addr;
618 {
619 struct ifaddr *ifaddr = ifa_ifwithnet( addr );
620 struct sockaddr_in *addr_in;
621 struct sockaddr_in *faddr_in;
622
623 if( !ifaddr ) {
624 OS_DbgPrint(OSK_MID_TRACE,("No ifaddr\n"));
625 return NULL;
626 } else {
627 OS_DbgPrint(OSK_MID_TRACE,("ifaddr @ %x\n", ifaddr));
628 }
629
630 addr_in = (struct sockaddr_in *)addr;
631 faddr_in = (struct sockaddr_in *)ifaddr->ifa_addr;
632
633 if( faddr_in->sin_addr.s_addr == addr_in->sin_addr.s_addr )
634 return ifaddr;
635 else
636 return NULL;
637 }
638
639 /*
640 * Locate the point to point interface with a given destination address.
641 */
642 /*ARGSUSED*/
643 struct ifaddr *
644 ifa_ifwithdstaddr(addr)
645 register struct sockaddr *addr;
646 {
647 OS_DbgPrint(OSK_MID_TRACE,("Called\n"));
648 return ifa_iffind(addr, IFF_POINTOPOINT);
649 }
650
651 /*
652 * Find an interface on a specific network. If many, choice
653 * is most specific found.
654 */
655 struct ifaddr *ifa_ifwithnet(addr)
656 struct sockaddr *addr;
657 {
658 struct sockaddr_in *sin;
659 struct ifaddr *ifaddr = ifa_iffind(addr, IFF_UNICAST);
660
661 if( ifaddr )
662 {
663 sin = (struct sockaddr_in *)&ifaddr->ifa_addr;
664
665 OS_DbgPrint(OSK_MID_TRACE,("ifaddr->addr = %x\n",
666 sin->sin_addr.s_addr));
667 }
668
669 return ifaddr;
670 }
671