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