03da96de05eca45dd6b19cbb7c65c5d55c5c6fc7
[reactos.git] / reactos / drivers / lib / oskittcp / oskittcp / interface.c
1 #include <oskittcp.h>
2 #include <oskitdebug.h>
3 #include <sys/param.h>
4 #include <sys/systm.h>
5 #include <sys/socket.h>
6 #include <sys/kernel.h>
7 #include <sys/filedesc.h>
8 #include <sys/proc.h>
9 #include <sys/fcntl.h>
10 #include <sys/file.h>
11 #include <sys/mbuf.h>
12 #include <sys/protosw.h>
13 #include <sys/socket.h>
14 #include <sys/socketvar.h>
15 #include <sys/uio.h>
16
17 struct linker_set domain_set;
18
19 OSKITTCP_EVENT_HANDLERS OtcpEvent = { 0 };
20
21 OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA;
22
23 /* SPL */
24 unsigned cpl;
25 unsigned net_imask;
26 unsigned volatile ipending;
27 struct timeval boottime;
28
29 void *fbsd_malloc( unsigned int bytes, const char *file, int line, ... ) {
30 if( !OtcpEvent.TCPMalloc ) panic("no malloc");
31 return OtcpEvent.TCPMalloc
32 ( OtcpEvent.ClientData,
33 (OSK_UINT)bytes, (OSK_PCHAR)file, (OSK_UINT)line );
34 }
35
36 void fbsd_free( void *data, const char *file, int line, ... ) {
37 if( !OtcpEvent.TCPFree ) panic("no free");
38 OtcpEvent.TCPFree( OtcpEvent.ClientData,
39 data, (OSK_PCHAR)file, (OSK_UINT)line );
40 }
41
42 void InitOskitTCP() {
43 OS_DbgPrint(OSK_MID_TRACE,("Init Called\n"));
44 OS_DbgPrint(OSK_MID_TRACE,("MB Init\n"));
45 mbinit();
46 OS_DbgPrint(OSK_MID_TRACE,("Rawip Init\n"));
47 rip_init();
48 raw_init();
49 OS_DbgPrint(OSK_MID_TRACE,("Route Init\n"));
50 route_init();
51 OS_DbgPrint(OSK_MID_TRACE,("Init fake freebsd scheduling\n"));
52 init_freebsd_sched();
53 OS_DbgPrint(OSK_MID_TRACE,("Init clock\n"));
54 clock_init();
55 OS_DbgPrint(OSK_MID_TRACE,("Init TCP\n"));
56 tcp_init();
57 OS_DbgPrint(OSK_MID_TRACE,("Init routing\n"));
58 domaininit();
59 memset( &OtcpEvent, 0, sizeof( OtcpEvent ) );
60 OS_DbgPrint(OSK_MID_TRACE,("Init Finished\n"));
61 tcp_iss = 1024;
62 }
63
64 void DeinitOskitTCP() {
65 }
66
67 void TimerOskitTCP() {
68 tcp_slowtimo();
69 tcp_fasttimo();
70 }
71
72 void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
73 memcpy( &OtcpEvent, EventHandlers, sizeof(OtcpEvent) );
74 if( OtcpEvent.PacketSend )
75 OS_DbgPrint(OSK_MID_TRACE,("SendPacket handler registered: %x\n",
76 OtcpEvent.PacketSend));
77 }
78
79 void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len ) {
80 unsigned int i;
81
82 for( i = 0; i < Len; i++ ) {
83 if( i && !(i & 0xf) ) DbgPrint( "\n" );
84 if( !(i & 0xf) ) DbgPrint( "%08x: ", (OSK_UINT)(Data + i) );
85 DbgPrint( " %02x", Data[i] );
86 }
87 DbgPrint("\n");
88 }
89
90 /* From uipc_syscalls.c */
91
92 int OskitTCPSocket( void *context,
93 void **aso,
94 int domain,
95 int type,
96 int proto )
97 {
98 struct socket *so;
99 int error = socreate(domain, &so, type, proto);
100 if( !error ) {
101 so->so_connection = context;
102 so->so_state = SS_NBIO;
103 *aso = so;
104 }
105 return error;
106 }
107
108 int OskitTCPRecv( void *connection,
109 OSK_PCHAR Data,
110 OSK_UINT Len,
111 OSK_UINT *OutLen,
112 OSK_UINT Flags ) {
113 struct mbuf *paddr = 0;
114 struct mbuf m, *mp;
115 struct uio uio = { 0 };
116 int error = 0;
117 int tcp_flags = 0;
118
119 if( Flags & OSK_MSG_OOB ) tcp_flags |= MSG_OOB;
120 if( Flags & OSK_MSG_DONTWAIT ) tcp_flags |= MSG_DONTWAIT;
121 if( Flags & OSK_MSG_PEEK ) tcp_flags |= MSG_PEEK;
122
123 uio.uio_resid = Len;
124 m.m_len = Len;
125 m.m_data = Data;
126 m.m_type = MT_DATA;
127 m.m_flags = M_PKTHDR | M_EOR;
128
129 mp = &m;
130
131 OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len));
132
133 error = soreceive( connection, &paddr, &uio, &mp, NULL /* SCM_RIGHTS */,
134 &tcp_flags );
135
136 if( error == 0 ) {
137 OS_DbgPrint(OSK_MID_TRACE,("Successful read from TCP:\n"));
138 OskitDumpBuffer( m.m_data, uio.uio_resid );
139 }
140
141 *OutLen = uio.uio_resid;
142 return error;
143 }
144
145 static int
146 getsockaddr(namp, uaddr, len)
147 /* [<][>][^][v][top][bottom][index][help] */
148 struct sockaddr **namp;
149 caddr_t uaddr;
150 size_t len;
151 {
152 struct sockaddr *sa;
153 int error;
154
155 if (len > SOCK_MAXADDRLEN)
156 return ENAMETOOLONG;
157 MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
158 error = copyin(uaddr, sa, len);
159 if (error) {
160 FREE(sa, M_SONAME);
161 } else {
162 *namp = sa;
163 }
164 return error;
165 }
166
167 int OskitTCPBind( void *socket, void *connection,
168 void *nam, OSK_UINT namelen ) {
169 int error = EFAULT;
170 struct socket *so = socket;
171 struct mbuf sabuf = { 0 };
172 struct sockaddr addr;
173
174 OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
175
176 if( nam )
177 addr = *((struct sockaddr *)nam);
178
179 sabuf.m_data = (void *)&addr;
180 sabuf.m_len = sizeof(addr);
181
182 addr.sa_family = addr.sa_len;
183 addr.sa_len = sizeof(struct sockaddr);
184
185 OskitDumpBuffer( (OSK_PCHAR)&addr, sizeof(addr) );
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 struct connect_args _uap = {
197 0, nam, namelen
198 }, *uap = &_uap;
199 int error = EFAULT, s;
200 struct mbuf sabuf = { 0 };
201 struct sockaddr addr;
202
203 OS_DbgPrint(OSK_MID_TRACE,("Called, socket = %08x\n", socket));
204
205 so->so_connection = connection;
206
207 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
208 error = EALREADY;
209 goto done;
210 }
211
212 OS_DbgPrint(OSK_MIN_TRACE,("Nam: %x\n", nam));
213 if( nam )
214 addr = *((struct sockaddr *)nam);
215
216 sabuf.m_data = (void *)&addr;
217 sabuf.m_len = sizeof(addr);
218
219 addr.sa_family = addr.sa_len;
220 addr.sa_len = sizeof(struct sockaddr);
221
222 error = soconnect(so, &sabuf);
223
224 if (error)
225 goto bad;
226
227 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
228 error = EINPROGRESS;
229 goto done;
230 }
231
232 bad:
233 so->so_state &= ~SS_ISCONNECTING;
234
235 if (error == ERESTART)
236 error = EINTR;
237
238 done:
239 OS_DbgPrint(OSK_MID_TRACE,("Ending: %08x\n", error));
240 return (error);
241 }
242
243 int OskitTCPClose( void *socket ) {
244 struct socket *so = socket;
245 so->so_connection = 0;
246 soclose( so );
247 return 0;
248 }
249
250 int OskitTCPSend( void *socket, OSK_PCHAR Data, OSK_UINT Len,
251 OSK_UINT *OutLen, OSK_UINT flags ) {
252 struct mbuf mb;
253 struct uio uio = { 0 };
254 int error = 0;
255 OskitDumpBuffer( Data, Len );
256 uio.uio_resid = Len;
257 mb.m_data = Data;
258 mb.m_len = Len;
259 mb.m_flags = M_EOR;
260 error = sosend( socket, NULL, &uio, (struct mbuf *)&mb, NULL, 0 );
261 printf("uio.uio_resid = %d\n", uio.uio_resid);
262 *OutLen = uio.uio_resid;
263 return error;
264 }
265
266 int OskitTCPAccept( void *socket,
267 void *AddrOut,
268 OSK_UINT AddrLen,
269 OSK_UINT *OutAddrLen ) {
270 struct mbuf nam;
271 int error;
272
273 nam.m_data = AddrOut;
274 nam.m_len = AddrLen;
275
276 return soaccept( socket, &nam );
277 }
278
279 /* The story so far
280 *
281 * We have a packet. While we store the fields we want in host byte order
282 * outside the original packet, the bsd stack modifies them in place.
283 */
284
285 void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
286 OSK_UINT IpHeaderLen ) {
287 struct mbuf *Ip = m_devget( Data, Len, 0, NULL, NULL );
288 struct ip *iph;
289
290 if( !Ip ) return; /* drop the segment */
291
292 memcpy( Ip->m_data, Data, Len );
293 Ip->m_pkthdr.len = IpHeaderLen;
294
295 /* Do the transformations on the header that tcp_input expects */
296 iph = mtod(Ip, struct ip *);
297 NTOHS(iph->ip_len);
298 iph->ip_len -= sizeof(struct ip);
299
300 OS_DbgPrint(OSK_MAX_TRACE,
301 ("OskitTCPReceiveDatagram: %d (%d header) Bytes\n", Len,
302 IpHeaderLen));
303
304 OskitDumpBuffer( Data, Len );
305
306 tcp_input(Ip, IpHeaderLen);
307
308 /* The buffer Ip is freed by tcp_input */
309 }
310
311 int OskitTCPListen( void *socket, int backlog ) {
312 return solisten( socket, backlog );
313 }
314
315 void OskitTCPSetAddress( void *socket,
316 OSK_UINT LocalAddress,
317 OSK_UI16 LocalPort,
318 OSK_UINT RemoteAddress,
319 OSK_UI16 RemotePort ) {
320 struct socket *so = socket;
321 struct inpcb *inp = so->so_pcb;
322 inp->inp_laddr.s_addr = LocalAddress;
323 inp->inp_lport = LocalPort;
324 inp->inp_faddr.s_addr = RemoteAddress;
325 inp->inp_fport = RemotePort;
326 DbgPrint("OSKIT: SET ADDR %x:%x -> %x:%x\n",
327 LocalAddress, LocalPort,
328 RemoteAddress, RemotePort);
329 }
330
331 void OskitTCPGetAddress( void *socket,
332 OSK_UINT *LocalAddress,
333 OSK_UI16 *LocalPort,
334 OSK_UINT *RemoteAddress,
335 OSK_UI16 *RemotePort ) {
336 struct socket *so = socket;
337 struct inpcb *inp = so ? so->so_pcb : 0;
338 if( inp ) {
339 *LocalAddress = inp->inp_laddr.s_addr;
340 *LocalPort = inp->inp_lport;
341 *RemoteAddress = inp->inp_faddr.s_addr;
342 *RemotePort = inp->inp_fport;
343 DbgPrint("OSKIT: GET ADDR %x:%x -> %x:%x\n",
344 *LocalAddress, *LocalPort,
345 *RemoteAddress, *RemotePort);
346 }
347 }
348
349 struct ifaddr *ifa_iffind(struct sockaddr *addr, int type)
350 {
351 if( OtcpEvent.FindInterface )
352 return OtcpEvent.FindInterface( OtcpEvent.ClientData,
353 PF_INET,
354 type,
355 addr );
356 else
357 return NULL;
358 }
359
360 void oskittcp_die( const char *file, int line ) {
361 DbgPrint("\n\n*** OSKITTCP: Panic Called at %s:%d ***\n", file, line);
362 *((int *)0) = 0;
363 }
364
365 /* Stuff supporting the BSD network-interface interface */
366 struct ifaddr **ifnet_addrs;
367 struct ifnet *ifnet;
368
369 void
370 ifinit()
371 {
372 }
373
374
375 void
376 if_attach(ifp)
377 struct ifnet *ifp;
378 {
379 panic("if_attach\n");
380 }
381
382 struct ifnet *
383 ifunit(char *name)
384 {
385 return 0;
386 }
387
388 /*
389 * Handle interface watchdog timer routines. Called
390 * from softclock, we decrement timers (if set) and
391 * call the appropriate interface routine on expiration.
392 */
393 void
394 if_slowtimo(arg)
395 void *arg;
396 {
397 #if 0
398 register struct ifnet *ifp;
399 int s = splimp();
400
401 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
402 if (ifp->if_timer == 0 || --ifp->if_timer)
403 continue;
404 if (ifp->if_watchdog)
405 (*ifp->if_watchdog)(ifp->if_unit);
406 }
407 splx(s);
408 timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
409 #endif
410 }
411
412 /*
413 * Locate an interface based on a complete address.
414 */
415
416 /*ARGSUSED*/
417 struct ifaddr *ifa_ifwithaddr(addr)
418 struct sockaddr *addr;
419 {
420 struct ifaddr *ifaddr = ifa_ifwithnet( addr );
421 struct sockaddr_in *addr_in;
422 struct sockaddr_in *faddr_in;
423
424 if( !ifaddr ) {
425 OS_DbgPrint(OSK_MID_TRACE,("No ifaddr\n"));
426 return NULL;
427 } else {
428 OS_DbgPrint(OSK_MID_TRACE,("ifaddr @ %x\n", ifaddr));
429 }
430
431 addr_in = (struct sockaddr_in *)addr;
432 faddr_in = (struct sockaddr_in *)ifaddr->ifa_addr;
433
434 if( faddr_in->sin_addr.s_addr == addr_in->sin_addr.s_addr )
435 return ifaddr;
436 else
437 return NULL;
438 }
439
440 /*
441 * Locate the point to point interface with a given destination address.
442 */
443 /*ARGSUSED*/
444 struct ifaddr *
445 ifa_ifwithdstaddr(addr)
446 register struct sockaddr *addr;
447 {
448 OS_DbgPrint(OSK_MID_TRACE,("Called\n"));
449 return ifa_iffind(addr, IFF_POINTOPOINT);
450 }
451
452 /*
453 * Find an interface on a specific network. If many, choice
454 * is most specific found.
455 */
456 struct ifaddr *ifa_ifwithnet(addr)
457 struct sockaddr *addr;
458 {
459 struct sockaddr_in *sin;
460 struct ifaddr *ifaddr = ifa_iffind(addr, IFF_UNICAST);
461
462 sin = (struct sockaddr *)&ifaddr->ifa_addr;
463
464 OS_DbgPrint(OSK_MID_TRACE,("ifaddr->addr = %x\n", sin->sin_addr.s_addr));
465
466 return ifaddr;
467 }
468