bfd12b0190d8bea9aaefa67bf34f1dae045a49ba
[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 struct linker_set domain_set;
19
20 OSKITTCP_EVENT_HANDLERS OtcpEvent = { 0 };
21
22 OSK_UINT OskitDebugTraceLevel = OSK_DEBUG_ULTRA;
23
24 /* SPL */
25 unsigned cpl;
26 unsigned net_imask;
27 unsigned volatile ipending;
28 struct timeval boottime;
29
30 void *fbsd_malloc( unsigned int bytes, ... ) {
31 if( !OtcpEvent.TCPMalloc ) panic("no malloc");
32 return OtcpEvent.TCPMalloc
33 ( OtcpEvent.ClientData, (OSK_UINT)bytes, "*", 0 );
34 }
35
36 void fbsd_free( void *data, ... ) {
37 if( !OtcpEvent.TCPFree ) panic("no free");
38 OtcpEvent.TCPFree( OtcpEvent.ClientData, data, "*", 0 );
39 }
40
41 void InitOskitTCP() {
42 OS_DbgPrint(OSK_MID_TRACE,("Init Called\n"));
43 OS_DbgPrint(OSK_MID_TRACE,("MB Init\n"));
44 mbinit();
45 OS_DbgPrint(OSK_MID_TRACE,("Rawip Init\n"));
46 rip_init();
47 raw_init();
48 OS_DbgPrint(OSK_MID_TRACE,("Route Init\n"));
49 route_init();
50 OS_DbgPrint(OSK_MID_TRACE,("Init fake freebsd scheduling\n"));
51 init_freebsd_sched();
52 OS_DbgPrint(OSK_MID_TRACE,("Init clock\n"));
53 clock_init();
54 OS_DbgPrint(OSK_MID_TRACE,("Init TCP\n"));
55 tcp_init();
56 OS_DbgPrint(OSK_MID_TRACE,("Init routing\n"));
57 domaininit();
58 OS_DbgPrint(OSK_MID_TRACE,("Init Finished\n"));
59 tcp_iss = 1024;
60 }
61
62 void DeinitOskitTCP() {
63 }
64
65 void TimerOskitTCP() {
66 tcp_slowtimo();
67 tcp_fasttimo();
68 }
69
70 void RegisterOskitTCPEventHandlers( POSKITTCP_EVENT_HANDLERS EventHandlers ) {
71 memcpy( &OtcpEvent, EventHandlers, sizeof(OtcpEvent) );
72 if( OtcpEvent.PacketSend )
73 OS_DbgPrint(OSK_MID_TRACE,("SendPacket handler registered: %x\n",
74 OtcpEvent.PacketSend));
75 }
76
77 void OskitDumpBuffer( OSK_PCHAR Data, OSK_UINT Len ) {
78 unsigned int i;
79
80 for( i = 0; i < Len; i++ ) {
81 if( i && !(i & 0xf) ) DbgPrint( "\n" );
82 if( !(i & 0xf) ) DbgPrint( "%08x: ", (OSK_UINT)(Data + i) );
83 DbgPrint( " %02x", Data[i] );
84 }
85 DbgPrint("\n");
86 }
87
88 /* From uipc_syscalls.c */
89
90 int OskitTCPSocket( void *context,
91 void **aso,
92 int domain,
93 int type,
94 int proto )
95 {
96 struct socket *so;
97 int error = socreate(domain, &so, type, proto);
98 if( !error ) {
99 so->so_connection = context;
100 so->so_state = SS_NBIO;
101 *aso = so;
102 }
103 return error;
104 }
105
106 int OskitTCPRecv( void *connection,
107 OSK_PCHAR Data,
108 OSK_UINT Len,
109 OSK_UINT *OutLen,
110 OSK_UINT Flags ) {
111 char *output_ptr = Data;
112 struct uio uio = { 0 };
113 struct iovec iov = { 0 };
114 int error = 0;
115 int tcp_flags = 0;
116 int tocopy = 0;
117
118 *OutLen = 0;
119
120 if( Flags & OSK_MSG_OOB ) tcp_flags |= MSG_OOB;
121 if( Flags & OSK_MSG_DONTWAIT ) tcp_flags |= MSG_DONTWAIT;
122 if( Flags & OSK_MSG_PEEK ) tcp_flags |= MSG_PEEK;
123
124 uio.uio_resid = Len;
125 uio.uio_iov = &iov;
126 uio.uio_rw = UIO_READ;
127 uio.uio_iovcnt = 1;
128 iov.iov_len = Len;
129 iov.iov_base = Data;
130
131 OS_DbgPrint(OSK_MID_TRACE,("Reading %d bytes from TCP:\n", Len));
132
133 error = soreceive( connection, NULL, &uio, NULL, NULL /* SCM_RIGHTS */,
134 &tcp_flags );
135
136 if( error == 0 ) {
137 OS_DbgPrint(OSK_MID_TRACE,("Successful read from TCP:\n"));
138 *OutLen = Len - uio.uio_resid;
139 OskitDumpBuffer( Data, *OutLen );
140 }
141
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* m = m_devget( Data, Len, 0, NULL, NULL );
253 int error = 0;
254 if ( !m )
255 return ENOBUFS;
256 OskitDumpBuffer( Data, Len );
257 error = sosend( socket, NULL, NULL, m, NULL, 0 );
258 *OutLen = Len;
259 return error;
260 }
261
262 int OskitTCPAccept( void *socket,
263 void *AddrOut,
264 OSK_UINT AddrLen,
265 OSK_UINT *OutAddrLen ) {
266 struct mbuf nam;
267 int error;
268
269 nam.m_data = AddrOut;
270 nam.m_len = AddrLen;
271
272 return soaccept( socket, &nam );
273 }
274
275 /* The story so far
276 *
277 * We have a packet. While we store the fields we want in host byte order
278 * outside the original packet, the bsd stack modifies them in place.
279 */
280
281 void OskitTCPReceiveDatagram( OSK_PCHAR Data, OSK_UINT Len,
282 OSK_UINT IpHeaderLen ) {
283 struct mbuf *Ip = m_devget( Data, Len, 0, NULL, NULL );
284 struct ip *iph;
285
286 if( !Ip ) return; /* drop the segment */
287
288 //memcpy( Ip->m_data, Data, Len );
289 Ip->m_pkthdr.len = IpHeaderLen;
290
291 /* Do the transformations on the header that tcp_input expects */
292 iph = mtod(Ip, struct ip *);
293 NTOHS(iph->ip_len);
294 iph->ip_len -= sizeof(struct ip);
295
296 OS_DbgPrint(OSK_MAX_TRACE,
297 ("OskitTCPReceiveDatagram: %d (%d header) Bytes\n", Len,
298 IpHeaderLen));
299
300 OskitDumpBuffer( Data, Len );
301
302 tcp_input(Ip, IpHeaderLen);
303
304 /* The buffer Ip is freed by tcp_input */
305 }
306
307 int OskitTCPListen( void *socket, int backlog ) {
308 return solisten( socket, backlog );
309 }
310
311 void OskitTCPSetAddress( void *socket,
312 OSK_UINT LocalAddress,
313 OSK_UI16 LocalPort,
314 OSK_UINT RemoteAddress,
315 OSK_UI16 RemotePort ) {
316 struct socket *so = socket;
317 struct inpcb *inp = so->so_pcb;
318 inp->inp_laddr.s_addr = LocalAddress;
319 inp->inp_lport = LocalPort;
320 inp->inp_faddr.s_addr = RemoteAddress;
321 inp->inp_fport = RemotePort;
322 DbgPrint("OSKIT: SET ADDR %x:%x -> %x:%x\n",
323 LocalAddress, LocalPort,
324 RemoteAddress, RemotePort);
325 }
326
327 void OskitTCPGetAddress( void *socket,
328 OSK_UINT *LocalAddress,
329 OSK_UI16 *LocalPort,
330 OSK_UINT *RemoteAddress,
331 OSK_UI16 *RemotePort ) {
332 struct socket *so = socket;
333 struct inpcb *inp = so ? so->so_pcb : 0;
334 if( inp ) {
335 *LocalAddress = inp->inp_laddr.s_addr;
336 *LocalPort = inp->inp_lport;
337 *RemoteAddress = inp->inp_faddr.s_addr;
338 *RemotePort = inp->inp_fport;
339 DbgPrint("OSKIT: GET ADDR %x:%x -> %x:%x\n",
340 *LocalAddress, *LocalPort,
341 *RemoteAddress, *RemotePort);
342 }
343 }
344
345 struct ifaddr *ifa_iffind(struct sockaddr *addr, int type)
346 {
347 if( OtcpEvent.FindInterface )
348 return OtcpEvent.FindInterface( OtcpEvent.ClientData,
349 PF_INET,
350 type,
351 addr );
352 else
353 return NULL;
354 }
355
356 void oskittcp_die( const char *file, int line ) {
357 DbgPrint("\n\n*** OSKITTCP: Panic Called at %s:%d ***\n", file, line);
358 *((int *)0) = 0;
359 }
360
361 /* Stuff supporting the BSD network-interface interface */
362 struct ifaddr **ifnet_addrs;
363 struct ifnet *ifnet;
364
365 void
366 ifinit()
367 {
368 }
369
370
371 void
372 if_attach(ifp)
373 struct ifnet *ifp;
374 {
375 panic("if_attach\n");
376 }
377
378 struct ifnet *
379 ifunit(char *name)
380 {
381 return 0;
382 }
383
384 /*
385 * Handle interface watchdog timer routines. Called
386 * from softclock, we decrement timers (if set) and
387 * call the appropriate interface routine on expiration.
388 */
389 void
390 if_slowtimo(arg)
391 void *arg;
392 {
393 #if 0
394 register struct ifnet *ifp;
395 int s = splimp();
396
397 for (ifp = ifnet; ifp; ifp = ifp->if_next) {
398 if (ifp->if_timer == 0 || --ifp->if_timer)
399 continue;
400 if (ifp->if_watchdog)
401 (*ifp->if_watchdog)(ifp->if_unit);
402 }
403 splx(s);
404 timeout(if_slowtimo, (void *)0, hz / IFNET_SLOWHZ);
405 #endif
406 }
407
408 /*
409 * Locate an interface based on a complete address.
410 */
411
412 /*ARGSUSED*/
413 struct ifaddr *ifa_ifwithaddr(addr)
414 struct sockaddr *addr;
415 {
416 struct ifaddr *ifaddr = ifa_ifwithnet( addr );
417 struct sockaddr_in *addr_in;
418 struct sockaddr_in *faddr_in;
419
420 if( !ifaddr ) {
421 OS_DbgPrint(OSK_MID_TRACE,("No ifaddr\n"));
422 return NULL;
423 } else {
424 OS_DbgPrint(OSK_MID_TRACE,("ifaddr @ %x\n", ifaddr));
425 }
426
427 addr_in = (struct sockaddr_in *)addr;
428 faddr_in = (struct sockaddr_in *)ifaddr->ifa_addr;
429
430 if( faddr_in->sin_addr.s_addr == addr_in->sin_addr.s_addr )
431 return ifaddr;
432 else
433 return NULL;
434 }
435
436 /*
437 * Locate the point to point interface with a given destination address.
438 */
439 /*ARGSUSED*/
440 struct ifaddr *
441 ifa_ifwithdstaddr(addr)
442 register struct sockaddr *addr;
443 {
444 OS_DbgPrint(OSK_MID_TRACE,("Called\n"));
445 return ifa_iffind(addr, IFF_POINTOPOINT);
446 }
447
448 /*
449 * Find an interface on a specific network. If many, choice
450 * is most specific found.
451 */
452 struct ifaddr *ifa_ifwithnet(addr)
453 struct sockaddr *addr;
454 {
455 struct sockaddr_in *sin;
456 struct ifaddr *ifaddr = ifa_iffind(addr, IFF_UNICAST);
457
458 if( ifaddr )
459 {
460 sin = (struct sockaddr *)&ifaddr->ifa_addr;
461
462 OS_DbgPrint(OSK_MID_TRACE,("ifaddr->addr = %x\n",
463 sin->sin_addr.s_addr));
464 }
465
466 return ifaddr;
467 }
468