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