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