- Improvements for select/implementation of event select.
[reactos.git] / reactos / drivers / lib / oskittcp / oskittcp / interface.c
1 #include <stdio.h>
2 #include <oskittcp.h>
3 #include <oskitdebug.h>
4 #include <sys/param.h>
5 #include <sys/systm.h>
6 #include <sys/socket.h>
7 #include <sys/kernel.h>
8 #include <sys/filedesc.h>
9 #include <sys/proc.h>
10 #include <sys/fcntl.h>
11 #include <sys/file.h>
12 #include <sys/mbuf.h>
13 #include <sys/protosw.h>
14 #include <sys/socket.h>
15 #include <sys/socketvar.h>
16 #include <sys/uio.h>
17
18 #ifdef WIN32
19 #define snprintf _snprintf
20 #endif//WIN32
21
22 struct linker_set domain_set;
23
24 OSKITTCP_EVENT_HANDLERS OtcpEvent = { 0 };
25
26 OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA;
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 *aso = so;
123 }
124 return error;
125 }
126
127 int OskitTCPRecv( void *connection,
128 OSK_PCHAR Data,
129 OSK_UINT Len,
130 OSK_UINT *OutLen,
131 OSK_UINT Flags ) {
132 char *output_ptr = Data;
133 struct uio uio = { 0 };
134 struct iovec iov = { 0 };
135 int error = 0;
136 int tcp_flags = 0;
137 int tocopy = 0;
138
139 *OutLen = 0;
140
141 if( Flags & OSK_MSG_OOB ) tcp_flags |= MSG_OOB;
142 if( Flags & OSK_MSG_DONTWAIT ) tcp_flags |= MSG_DONTWAIT;
143 if( Flags & OSK_MSG_PEEK ) tcp_flags |= MSG_PEEK;
144
145 uio.uio_resid = Len;
146 uio.uio_iov = &iov;
147 uio.uio_rw = UIO_READ;
148 uio.uio_iovcnt = 1;
149 iov.iov_len = Len;
150 iov.iov_base = Data;
151
152 OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len));
153
154 error = soreceive( connection, NULL, &uio, NULL, NULL /* SCM_RIGHTS */,
155 &tcp_flags );
156
157 if( error == 0 ) {
158 *OutLen = Len - uio.uio_resid;
159 }
160
161 return error;
162 }
163
164 static int
165 getsockaddr(namp, uaddr, len)
166 /* [<][>][^][v][top][bottom][index][help] */
167 struct sockaddr **namp;
168 caddr_t uaddr;
169 size_t len;
170 {
171 struct sockaddr *sa;
172 int error;
173
174 if (len > SOCK_MAXADDRLEN)
175 return ENAMETOOLONG;
176 MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
177 error = copyin(uaddr, sa, len);
178 if (error) {
179 FREE(sa, M_SONAME);
180 } else {
181 *namp = sa;
182 }
183 return error;
184 }
185
186 int OskitTCPBind( void *socket, void *connection,
187 void *nam, OSK_UINT namelen ) {
188 int error = EFAULT;
189 struct socket *so = socket;
190 struct mbuf sabuf = { 0 };
191 struct sockaddr addr;
192
193 OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
194
195 if( nam )
196 addr = *((struct sockaddr *)nam);
197
198 sabuf.m_data = (void *)&addr;
199 sabuf.m_len = sizeof(addr);
200
201 addr.sa_family = addr.sa_len;
202 addr.sa_len = sizeof(struct sockaddr);
203
204 error = sobind(so, &sabuf);
205
206 OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
207 return (error);
208 }
209
210 int OskitTCPConnect( void *socket, void *connection,
211 void *nam, OSK_UINT namelen ) {
212 struct socket *so = socket;
213 struct connect_args _uap = {
214 0, nam, namelen
215 }, *uap = &_uap;
216 int error = EFAULT, s;
217 struct mbuf sabuf = { 0 };
218 struct sockaddr addr;
219
220 OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
221
222 so->so_connection = connection;
223
224 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
225 error = EALREADY;
226 goto done;
227 }
228
229 OS_DbgPrint(OSK_MIN_TRACE,("Nam: %x\n", nam));
230 if( nam )
231 addr = *((struct sockaddr *)nam);
232
233 sabuf.m_data = (void *)&addr;
234 sabuf.m_len = sizeof(addr);
235
236 addr.sa_family = addr.sa_len;
237 addr.sa_len = sizeof(struct sockaddr);
238
239 error = soconnect(so, &sabuf);
240
241 if (error)
242 goto bad;
243
244 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
245 error = EINPROGRESS;
246 goto done;
247 }
248
249 bad:
250 so->so_state &= ~SS_ISCONNECTING;
251
252 if (error == ERESTART)
253 error = EINTR;
254
255 done:
256 OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
257 return (error);
258 }
259
260 int OskitTCPClose( void *socket ) {
261 struct socket *so = socket;
262 so->so_connection = 0;
263 soclose( so );
264 return 0;
265 }
266
267 int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
268 OSK_UINT *OutLen, OSK_UINT flags ) {
269 struct mbuf* m = m_devget( Data, Len, 0, NULL, NULL );
270 int error = 0;
271 if ( !m )
272 return ENOBUFS;
273 error = sosend( socket, NULL, NULL, m, NULL, 0 );
274 *OutLen = Len;
275 return error;
276 }
277
278 int OskitTCPAccept( void *socket,
279 void *AddrOut,
280 OSK_UINT AddrLen,
281 OSK_UINT *OutAddrLen ) {
282 struct mbuf nam;
283 int error;
284
285 nam.m_data = AddrOut;
286 nam.m_len = AddrLen;
287
288 return soaccept( socket, &nam );
289 }
290
291 /* The story so far
292 *
293 * We have a packet. While we store the fields we want in host byte order
294 * outside the original packet, the bsd stack modifies them in place.
295 */
296
297 void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
298 OSK_UINT IpHeaderLen ) {
299 struct mbuf *Ip = m_devget( Data, Len, 0, NULL, NULL );
300 struct ip *iph;
301
302 if( !Ip ) return; /* drop the segment */
303
304 //memcpy( Ip->m_data, Data, Len );
305 Ip->m_pkthdr.len = IpHeaderLen;
306
307 /* Do the transformations on the header that tcp_input expects */
308 iph = mtod(Ip, struct ip *);
309 NTOHS(iph->ip_len);
310 iph->ip_len -= sizeof(struct ip);
311
312 OS_DbgPrint(OSK_MAX_TRACE,
313 ("OskitTCPReceiveDatagram: %d (%d header) Bytes\n", Len,
314 IpHeaderLen));
315
316 tcp_input(Ip, IpHeaderLen);
317
318 /* The buffer Ip is freed by tcp_input */
319 }
320
321 int OskitTCPListen( void *socket, int backlog ) {
322 return solisten( socket, backlog );
323 }
324
325 void OskitTCPSetAddress( void *socket,
326 OSK_UINT LocalAddress,
327 OSK_UI16 LocalPort,
328 OSK_UINT RemoteAddress,
329 OSK_UI16 RemotePort ) {
330 struct socket *so = socket;
331 struct inpcb *inp = so->so_pcb;
332 inp->inp_laddr.s_addr = LocalAddress;
333 inp->inp_lport = LocalPort;
334 inp->inp_faddr.s_addr = RemoteAddress;
335 inp->inp_fport = RemotePort;
336 DbgPrint("OSKIT: SET ADDR %x:%x -> %x:%x\n",
337 LocalAddress, LocalPort,
338 RemoteAddress, RemotePort);
339 }
340
341 void OskitTCPGetAddress( void *socket,
342 OSK_UINT *LocalAddress,
343 OSK_UI16 *LocalPort,
344 OSK_UINT *RemoteAddress,
345 OSK_UI16 *RemotePort ) {
346 struct socket *so = socket;
347 struct inpcb *inp = so ? so->so_pcb : 0;
348 if( inp ) {
349 *LocalAddress = inp->inp_laddr.s_addr;
350 *LocalPort = inp->inp_lport;
351 *RemoteAddress = inp->inp_faddr.s_addr;
352 *RemotePort = inp->inp_fport;
353 DbgPrint("OSKIT: GET ADDR %x:%x -> %x:%x\n",
354 *LocalAddress, *LocalPort,
355 *RemoteAddress, *RemotePort);
356 }
357 }
358
359 struct ifaddr *ifa_iffind(struct sockaddr *addr, int type)
360 {
361 if( OtcpEvent.FindInterface )
362 return OtcpEvent.FindInterface( OtcpEvent.ClientData,
363 PF_INET,
364 type,
365 addr );
366 else
367 return NULL;
368 }
369
370 void oskittcp_die( const char *file, int line ) {
371 DbgPrint("\n\n*** OSKITTCP: Panic Called at %s:%d ***\n", file, line);
372 *((int *)0) = 0;
373 }
374
375 /* Stuff supporting the BSD network-interface interface */
376 struct ifaddr **ifnet_addrs;
377 struct ifnet *ifnet;
378
379 void
380 ifinit()
381 {
382 }
383
384
385 void
386 if_attach(ifp)
387 struct ifnet *ifp;
388 {
389 panic("if_attach\n");
390 }
391
392 struct ifnet *
393 ifunit(char *name)
394 {
395 return 0;
396 }
397
398 /*
399 * Handle interface watchdog timer routines. Called
400 * from softclock, we decrement timers (if set) and
401 * call the appropriate interface routine on expiration.
402 */
403 void
404 if_slowtimo(arg)
405 void *arg;
406 {
407 #if 0
408 register struct ifnet *ifp;
409 int s = splimp();
410
411 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
412 if (ifp->if_timer == 0 || --ifp->if_timer)
413 continue;
414 if (ifp->if_watchdog)
415 (*ifp->if_watchdog)(ifp->if_unit);
416 }
417 splx(s);
418 timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
419 #endif
420 }
421
422 /*
423 * Locate an interface based on a complete address.
424 */
425
426 /*ARGSUSED*/
427 struct ifaddr *ifa_ifwithaddr(addr)
428 struct sockaddr *addr;
429 {
430 struct ifaddr *ifaddr = ifa_ifwithnet( addr );
431 struct sockaddr_in *addr_in;
432 struct sockaddr_in *faddr_in;
433
434 if( !ifaddr ) {
435 OS_DbgPrint(OSK_MID_TRACE,("No ifaddr\n"));
436 return NULL;
437 } else {
438 OS_DbgPrint(OSK_MID_TRACE,("ifaddr @ %x\n", ifaddr));
439 }
440
441 addr_in = (struct sockaddr_in *)addr;
442 faddr_in = (struct sockaddr_in *)ifaddr->ifa_addr;
443
444 if( faddr_in->sin_addr.s_addr == addr_in->sin_addr.s_addr )
445 return ifaddr;
446 else
447 return NULL;
448 }
449
450 /*
451 * Locate the point to point interface with a given destination address.
452 */
453 /*ARGSUSED*/
454 struct ifaddr *
455 ifa_ifwithdstaddr(addr)
456 register struct sockaddr *addr;
457 {
458 OS_DbgPrint(OSK_MID_TRACE,("Called\n"));
459 return ifa_iffind(addr, IFF_POINTOPOINT);
460 }
461
462 /*
463 * Find an interface on a specific network. If many, choice
464 * is most specific found.
465 */
466 struct ifaddr *ifa_ifwithnet(addr)
467 struct sockaddr *addr;
468 {
469 struct sockaddr_in *sin;
470 struct ifaddr *ifaddr = ifa_iffind(addr, IFF_UNICAST);
471
472 if( ifaddr )
473 {
474 sin = (struct sockaddr *)&ifaddr->ifa_addr;
475
476 OS_DbgPrint(OSK_MID_TRACE,("ifaddr->addr = %x\n",
477 sin->sin_addr.s_addr));
478 }
479
480 return ifaddr;
481 }
482