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