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