- Get IP to compile.
[reactos.git] / reactos / drivers / lib / 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 isprint(int c);
34 int _snprintf(char * buf, size_t cnt, const char *fmt, ...);
35
36 void *fbsd_malloc( unsigned int bytes, char *file, unsigned line, ... ) {
37 if( !OtcpEvent.TCPMalloc ) panic("no malloc");
38 return OtcpEvent.TCPMalloc
39 ( OtcpEvent.ClientData, (OSK_UINT)bytes, file, line );
40 }
41
42 void fbsd_free( void *data, char *file, unsigned line, ... ) {
43 if( !OtcpEvent.TCPFree ) panic("no free");
44 OtcpEvent.TCPFree( OtcpEvent.ClientData, data, file, line );
45 }
46
47 void InitOskitTCP() {
48 OS_DbgPrint(OSK_MID_TRACE,("Init Called\n"));
49 OS_DbgPrint(OSK_MID_TRACE,("MB Init\n"));
50 mbinit();
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 if ( SlowTimer ) {
71 tcp_slowtimo();
72 }
73 if ( FastTimer ) {
74 tcp_fasttimo();
75 }
76 }
77
78 void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
79 memcpy( &OtcpEvent, EventHandlers, sizeof(OtcpEvent) );
80 if( OtcpEvent.PacketSend )
81 OS_DbgPrint(OSK_MID_TRACE,("SendPacket handler registered: %x\n",
82 OtcpEvent.PacketSend));
83 }
84
85 void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len )
86 {
87 unsigned int i;
88 char line[81];
89 static const char* hex = "0123456789abcdef";
90
91 for ( i = 0; i < Len; i++ )
92 {
93 int align = i & 0xf;
94 int align3 = (align<<1) + align;
95 unsigned char c = Data[i];
96 if ( !align )
97 {
98 if ( i ) DbgPrint( line );
99 _snprintf ( line, sizeof(line)-1, "%08x: \n", &Data[i] );
100 line[sizeof(line)-1] = '\0';
101 }
102
103 line[10+align3] = hex[(c>>4)&0xf];
104 line[11+align3] = hex[c&0xf];
105 if ( !isprint(c) )
106 c = '.';
107 line[59+align] = c;
108 }
109 if ( Len & 0xf )
110 DbgPrint ( line );
111 }
112
113 /* From uipc_syscalls.c */
114
115 int OskitTCPSocket( void *context,
116 void **aso,
117 int domain,
118 int type,
119 int proto )
120 {
121 struct socket *so;
122 int error = socreate(domain, &so, type, proto);
123 if( !error ) {
124 so->so_connection = context;
125 so->so_state = SS_NBIO;
126 so->so_error = 0;
127 so->so_q = so->so_q0 = NULL;
128 so->so_qlen = 0;
129 so->so_head = NULL;
130 *aso = so;
131 }
132 return error;
133 }
134
135 int OskitTCPRecv( void *connection,
136 OSK_PCHAR Data,
137 OSK_UINT Len,
138 OSK_UINT *OutLen,
139 OSK_UINT Flags ) {
140 struct uio uio = { 0 };
141 struct iovec iov = { 0 };
142 int error = 0;
143 int tcp_flags = 0;
144
145 *OutLen = 0;
146
147 OS_DbgPrint(OSK_MID_TRACE,
148 ("so->so_state %x\n", ((struct socket *)connection)->so_state));
149
150 if( Flags & OSK_MSG_OOB ) tcp_flags |= MSG_OOB;
151 if( Flags & OSK_MSG_DONTWAIT ) tcp_flags |= MSG_DONTWAIT;
152 if( Flags & OSK_MSG_PEEK ) tcp_flags |= MSG_PEEK;
153
154 uio.uio_resid = Len;
155 uio.uio_iov = &iov;
156 uio.uio_rw = UIO_READ;
157 uio.uio_iovcnt = 1;
158 iov.iov_len = Len;
159 iov.iov_base = Data;
160
161 OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len));
162
163 error = soreceive( connection, NULL, &uio, NULL, NULL /* SCM_RIGHTS */,
164 &tcp_flags );
165
166 if( error == 0 ) {
167 *OutLen = Len - uio.uio_resid;
168 }
169
170 return error;
171 }
172
173 int OskitTCPBind( void *socket, void *connection,
174 void *nam, OSK_UINT namelen ) {
175 int error = EFAULT;
176 struct socket *so = socket;
177 struct mbuf sabuf;
178 struct sockaddr addr;
179
180 OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
181
182 if( nam )
183 addr = *((struct sockaddr *)nam);
184
185 RtlZeroMemory(&sabuf, sizeof(sabuf));
186 sabuf.m_data = (void *)&addr;
187 sabuf.m_len = sizeof(addr);
188
189 addr.sa_family = addr.sa_len;
190 addr.sa_len = sizeof(struct sockaddr);
191
192 error = sobind(so, &sabuf);
193
194 OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
195 return (error);
196 }
197
198 int OskitTCPConnect( void *socket, void *connection,
199 void *nam, OSK_UINT namelen ) {
200 struct socket *so = socket;
201 int error = EFAULT;
202 struct mbuf sabuf;
203 struct sockaddr addr;
204
205 OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
206
207 so->so_connection = connection;
208
209 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
210 error = EALREADY;
211 goto done;
212 }
213
214 OS_DbgPrint(OSK_MIN_TRACE,("Nam: %x\n", nam));
215 if( nam )
216 addr = *((struct sockaddr *)nam);
217
218 RtlZeroMemory(&sabuf, sizeof(sabuf));
219 sabuf.m_data = (void *)&addr;
220 sabuf.m_len = sizeof(addr);
221
222 addr.sa_family = addr.sa_len;
223 addr.sa_len = sizeof(struct sockaddr);
224
225 error = soconnect(so, &sabuf);
226
227 if (error)
228 goto bad;
229
230 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
231 error = EINPROGRESS;
232 goto done;
233 }
234
235 bad:
236 so->so_state &= ~SS_ISCONNECTING;
237
238 if (error == ERESTART)
239 error = EINTR;
240
241 done:
242 OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
243 return (error);
244 }
245
246 int OskitTCPShutdown( void *socket, int disconn_type ) {
247 return soshutdown( socket, disconn_type );
248 }
249
250 int OskitTCPClose( void *socket ) {
251 struct socket *so = socket;
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 iov.iov_len = Len;
264 iov.iov_base = Data;
265 uio.uio_iov = &iov;
266 uio.uio_iovcnt = 1;
267 uio.uio_offset = 0;
268 uio.uio_resid = Len;
269 uio.uio_segflg = UIO_SYSSPACE;
270 uio.uio_rw = UIO_WRITE;
271 uio.uio_procp = NULL;
272
273 error = sosend( socket, NULL, &uio, NULL, NULL, 0 );
274 if (OSK_EWOULDBLOCK == error) {
275 ((struct socket *) socket)->so_snd.sb_flags |= SB_WAIT;
276 }
277 *OutLen = uio.uio_offset;
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 OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Doing accept (Finish %d)\n",
298 FinishAccepting));
299
300 *OutAddrLen = AddrLen;
301
302 if (name)
303 /* that's a copyin actually */
304 namelen = *OutAddrLen;
305
306 s = splnet();
307
308 #if 0
309 if ((head->so_options & SO_ACCEPTCONN) == 0) {
310 splx(s);
311 OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: head->so_options = %x, wanted bit %x\n",
312 head->so_options, SO_ACCEPTCONN));
313 error = EINVAL;
314 goto out;
315 }
316 #endif
317
318 OS_DbgPrint(OSK_MID_TRACE,("head->so_q = %x, head->so_state = %x\n",
319 head->so_q, head->so_state));
320
321 if ((head->so_state & SS_NBIO) && head->so_q == NULL) {
322 splx(s);
323 error = EWOULDBLOCK;
324 goto out;
325 }
326
327 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
328 while (head->so_q == NULL && head->so_error == 0) {
329 if (head->so_state & SS_CANTRCVMORE) {
330 head->so_error = ECONNABORTED;
331 break;
332 }
333 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
334 error = tsleep((caddr_t)&head->so_timeo, PSOCK | PCATCH,
335 "accept", 0);
336 if (error) {
337 splx(s);
338 goto out;
339 }
340 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
341 }
342 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
343
344 #if 0
345 if (head->so_error) {
346 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
347 error = head->so_error;
348 head->so_error = 0;
349 splx(s);
350 goto out;
351 }
352 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
353 #endif
354
355 /*
356 * At this point we know that there is at least one connection
357 * ready to be accepted. Remove it from the queue.
358 */
359 so = head->so_q;
360
361 inp = so ? (struct inpcb *)so->so_pcb : NULL;
362 if( inp ) {
363 ((struct sockaddr_in *)AddrOut)->sin_addr.s_addr =
364 inp->inp_faddr.s_addr;
365 ((struct sockaddr_in *)AddrOut)->sin_port = inp->inp_fport;
366 }
367
368 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
369 if( FinishAccepting ) {
370 head->so_q = so->so_q;
371 head->so_qlen--;
372
373 *newso = so;
374
375 /*so->so_state &= ~SS_COMP;*/
376
377 mnam.m_data = (char *)&sa;
378 mnam.m_len = sizeof(sa);
379
380 (void) soaccept(so, &mnam);
381
382 so->so_state = SS_NBIO | SS_ISCONNECTED;
383 so->so_q = so->so_q0 = NULL;
384 so->so_qlen = 0;
385 so->so_head = 0;
386
387 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
388 if (name) {
389 /* check sa_len before it is destroyed */
390 memcpy( AddrOut, &sa, AddrLen < sizeof(sa) ? AddrLen : sizeof(sa) );
391 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
392 *OutAddrLen = namelen; /* copyout actually */
393 }
394 OS_DbgPrint(OSK_MID_TRACE,("error = %d\n", error));
395 splx(s);
396 }
397 out:
398 OS_DbgPrint(OSK_MID_TRACE,("OSKITTCP: Returning %d\n", error));
399 return (error);
400 }
401
402 /* The story so far
403 *
404 * We have a packet. While we store the fields we want in host byte order
405 * outside the original packet, the bsd stack modifies them in place.
406 */
407
408 void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
409 OSK_UINT IpHeaderLen ) {
410 struct mbuf *Ip = m_devget( Data, Len, 0, NULL, NULL );
411 struct ip *iph;
412
413 if( !Ip ) return; /* drop the segment */
414
415 //memcpy( Ip->m_data, Data, Len );
416 Ip->m_pkthdr.len = IpHeaderLen;
417
418 /* Do the transformations on the header that tcp_input expects */
419 iph = mtod(Ip, struct ip *);
420 NTOHS(iph->ip_len);
421 iph->ip_len -= sizeof(struct ip);
422
423 OS_DbgPrint(OSK_MAX_TRACE,
424 ("OskitTCPReceiveDatagram: %d (%d header) Bytes\n", Len,
425 IpHeaderLen));
426
427 tcp_input(Ip, IpHeaderLen);
428
429 /* The buffer Ip is freed by tcp_input */
430 }
431
432 int OskitTCPListen( void *socket, int backlog ) {
433 int error;
434
435 OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
436 error = solisten( socket, backlog );
437 OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
438
439 return error;
440 }
441
442 void OskitTCPSetAddress( void *socket,
443 OSK_UINT LocalAddress,
444 OSK_UI16 LocalPort,
445 OSK_UINT RemoteAddress,
446 OSK_UI16 RemotePort ) {
447 struct socket *so = socket;
448 struct inpcb *inp = (struct inpcb *)so->so_pcb;
449 inp->inp_laddr.s_addr = LocalAddress;
450 inp->inp_lport = LocalPort;
451 inp->inp_faddr.s_addr = RemoteAddress;
452 inp->inp_fport = RemotePort;
453 }
454
455 void OskitTCPGetAddress( void *socket,
456 OSK_UINT *LocalAddress,
457 OSK_UI16 *LocalPort,
458 OSK_UINT *RemoteAddress,
459 OSK_UI16 *RemotePort ) {
460 struct socket *so = socket;
461 struct inpcb *inp = so ? (struct inpcb *)so->so_pcb : NULL;
462 if( inp ) {
463 *LocalAddress = inp->inp_laddr.s_addr;
464 *LocalPort = inp->inp_lport;
465 *RemoteAddress = inp->inp_faddr.s_addr;
466 *RemotePort = inp->inp_fport;
467 }
468 }
469
470 struct ifaddr *ifa_iffind(struct sockaddr *addr, int type)
471 {
472 if( OtcpEvent.FindInterface )
473 return OtcpEvent.FindInterface( OtcpEvent.ClientData,
474 PF_INET,
475 type,
476 addr );
477 else
478 return NULL;
479 }
480
481 void oskittcp_die( const char *file, int line ) {
482 DbgPrint("\n\n*** OSKITTCP: Panic Called at %s:%d ***\n", file, line);
483 *((int *)0) = 0;
484 }
485
486 /* Stuff supporting the BSD network-interface interface */
487 struct ifaddr **ifnet_addrs;
488 struct ifnet *ifnet;
489
490 void
491 ifinit()
492 {
493 }
494
495
496 void
497 if_attach(ifp)
498 struct ifnet *ifp;
499 {
500 panic("if_attach\n");
501 }
502
503 struct ifnet *
504 ifunit(char *name)
505 {
506 return 0;
507 }
508
509 /*
510 * Handle interface watchdog timer routines. Called
511 * from softclock, we decrement timers (if set) and
512 * call the appropriate interface routine on expiration.
513 */
514 void
515 if_slowtimo(arg)
516 void *arg;
517 {
518 #if 0
519 register struct ifnet *ifp;
520 int s = splimp();
521
522 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
523 if (ifp->if_timer == 0 || --ifp->if_timer)
524 continue;
525 if (ifp->if_watchdog)
526 (*ifp->if_watchdog)(ifp->if_unit);
527 }
528 splx(s);
529 timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
530 #endif
531 }
532
533 /*
534 * Locate an interface based on a complete address.
535 */
536
537 /*ARGSUSED*/
538 struct ifaddr *ifa_ifwithaddr(addr)
539 struct sockaddr *addr;
540 {
541 struct ifaddr *ifaddr = ifa_ifwithnet( addr );
542 struct sockaddr_in *addr_in;
543 struct sockaddr_in *faddr_in;
544
545 if( !ifaddr ) {
546 OS_DbgPrint(OSK_MID_TRACE,("No ifaddr\n"));
547 return NULL;
548 } else {
549 OS_DbgPrint(OSK_MID_TRACE,("ifaddr @ %x\n", ifaddr));
550 }
551
552 addr_in = (struct sockaddr_in *)addr;
553 faddr_in = (struct sockaddr_in *)ifaddr->ifa_addr;
554
555 if( faddr_in->sin_addr.s_addr == addr_in->sin_addr.s_addr )
556 return ifaddr;
557 else
558 return NULL;
559 }
560
561 /*
562 * Locate the point to point interface with a given destination address.
563 */
564 /*ARGSUSED*/
565 struct ifaddr *
566 ifa_ifwithdstaddr(addr)
567 register struct sockaddr *addr;
568 {
569 OS_DbgPrint(OSK_MID_TRACE,("Called\n"));
570 return ifa_iffind(addr, IFF_POINTOPOINT);
571 }
572
573 /*
574 * Find an interface on a specific network. If many, choice
575 * is most specific found.
576 */
577 struct ifaddr *ifa_ifwithnet(addr)
578 struct sockaddr *addr;
579 {
580 struct sockaddr_in *sin;
581 struct ifaddr *ifaddr = ifa_iffind(addr, IFF_UNICAST);
582
583 if( ifaddr )
584 {
585 sin = (struct sockaddr_in *)&ifaddr->ifa_addr;
586
587 OS_DbgPrint(OSK_MID_TRACE,("ifaddr->addr = %x\n",
588 sin->sin_addr.s_addr));
589 }
590
591 return ifaddr;
592 }
593