1 #include "slirp.h"
2 
3 /* host address */
4 struct in_addr our_addr;
5 /* host dns address */
6 struct in_addr dns_addr;
7 /* host loopback address */
8 struct in_addr loopback_addr;
9 
10 /* address for slirp virtual addresses */
11 struct in_addr special_addr;
12 
13 const uint8_t special_ethaddr[6] = {
14     0x52, 0x54, 0x00, 0x12, 0x35, 0x00
15 };
16 
17 uint8_t client_ethaddr[6];
18 
19 int do_slowtimo;
20 int link_up;
21 struct timeval tt;
22 FILE *lfd;
23 
24 /* XXX: suppress those select globals */
25 fd_set *global_readfds, *global_writefds, *global_xfds;
26 
27 #ifdef _WIN32
28 
get_dns_addr(struct in_addr * pdns_addr)29 static int get_dns_addr(struct in_addr *pdns_addr)
30 {
31     /* XXX: add it */
32     return -1;
33 }
34 
35 #else
36 
get_dns_addr(struct in_addr * pdns_addr)37 static int get_dns_addr(struct in_addr *pdns_addr)
38 {
39     char buff[512];
40     char buff2[256];
41     FILE *f;
42     int found = 0;
43     struct in_addr tmp_addr;
44 
45     f = fopen("/etc/resolv.conf", "r");
46     if (!f)
47         return -1;
48 
49     lprint("IP address of your DNS(s): ");
50     while (fgets(buff, 512, f) != NULL) {
51         if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
52             if (!inet_aton(buff2, &tmp_addr))
53                 continue;
54             if (tmp_addr.s_addr == loopback_addr.s_addr)
55                 tmp_addr = our_addr;
56             /* If it's the first one, set it to dns_addr */
57             if (!found)
58                 *pdns_addr = tmp_addr;
59             else
60                 lprint(", ");
61             if (++found > 3) {
62                 lprint("(more)");
63                 break;
64             } else
65                 lprint("%s", inet_ntoa(tmp_addr));
66         }
67     }
68     if (!found)
69         return -1;
70     return 0;
71 }
72 
73 #endif
74 
slirp_init(char * network)75 void slirp_init(char *network)
76 {
77     debug_init("/tmp/slirp.log", DEBUG_DEFAULT);
78 
79     link_up = 1;
80 
81     if_init();
82     ip_init();
83 
84     /* Initialise mbufs *after* setting the MTU */
85     m_init();
86 
87     /* set default addresses */
88     getouraddr();
89     inet_aton("127.0.0.1", &loopback_addr);
90 
91     if (get_dns_addr(&dns_addr) < 0) {
92         fprintf(stderr, "Could not get DNS address\n");
93         exit(1);
94     }
95 
96     if (network==NULL)
97 	    inet_aton(CTL_SPECIAL, &special_addr);
98     else
99 	    inet_aton(network, &special_addr);
100 
101 }
102 
103 #define CONN_CANFSEND(so) (((so)->so_state & (SS_FCANTSENDMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
104 #define CONN_CANFRCV(so) (((so)->so_state & (SS_FCANTRCVMORE|SS_ISFCONNECTED)) == SS_ISFCONNECTED)
105 #define UPD_NFDS(x) if (nfds < (x)) nfds = (x)
106 
107 /*
108  * curtime kept to an accuracy of 1ms
109  */
updtime(void)110 static void updtime(void)
111 {
112 	gettimeofday(&tt, 0);
113 
114 	curtime = (u_int)tt.tv_sec * (u_int)1000;
115 	curtime += (u_int)tt.tv_usec / (u_int)1000;
116 
117 	if ((tt.tv_usec % 1000) >= 500)
118 	   curtime++;
119 }
120 
slirp_select_fill(int * pnfds,fd_set * readfds,fd_set * writefds,fd_set * xfds)121 void slirp_select_fill(int *pnfds,
122                        fd_set *readfds, fd_set *writefds, fd_set *xfds)
123 {
124     struct socket *so, *so_next;
125     struct timeval timeout;
126     int nfds;
127     int tmp_time;
128 
129     /* fail safe */
130     global_readfds = NULL;
131     global_writefds = NULL;
132     global_xfds = NULL;
133 
134     nfds = *pnfds;
135 	/*
136 	 * First, TCP sockets
137 	 */
138 	do_slowtimo = 0;
139 	if (link_up) {
140 		/*
141 		 * *_slowtimo needs calling if there are IP fragments
142 		 * in the fragment queue, or there are TCP connections active
143 		 */
144 		do_slowtimo = ((tcb.so_next != &tcb) ||
145 			       ((struct ipasfrag *)&ipq != (struct ipasfrag *)ipq.next));
146 
147 		for (so = tcb.so_next; so != &tcb; so = so_next) {
148 			so_next = so->so_next;
149 
150 			/*
151 			 * See if we need a tcp_fasttimo
152 			 */
153 			if (time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK)
154 			   time_fasttimo = curtime; /* Flag when we want a fasttimo */
155 
156 			/*
157 			 * NOFDREF can include still connecting to local-host,
158 			 * newly socreated() sockets etc. Don't want to select these.
159 	 		 */
160 			if (so->so_state & SS_NOFDREF || so->s == -1)
161 			   continue;
162 
163 			/*
164 			 * Set for reading sockets which are accepting
165 			 */
166 			if (so->so_state & SS_FACCEPTCONN) {
167                                 FD_SET(so->s, readfds);
168 				UPD_NFDS(so->s);
169 				continue;
170 			}
171 
172 			/*
173 			 * Set for writing sockets which are connecting
174 			 */
175 			if (so->so_state & SS_ISFCONNECTING) {
176 				FD_SET(so->s, writefds);
177 				UPD_NFDS(so->s);
178 				continue;
179 			}
180 
181 			/*
182 			 * Set for writing if we are connected, can send more, and
183 			 * we have something to send
184 			 */
185 			if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
186 				FD_SET(so->s, writefds);
187 				UPD_NFDS(so->s);
188 			}
189 
190 			/*
191 			 * Set for reading (and urgent data) if we are connected, can
192 			 * receive more, and we have room for it XXX /2 ?
193 			 */
194 			if (CONN_CANFRCV(so) && (so->so_snd.sb_cc < (so->so_snd.sb_datalen/2))) {
195 				FD_SET(so->s, readfds);
196 				FD_SET(so->s, xfds);
197 				UPD_NFDS(so->s);
198 			}
199 		}
200 
201 		/*
202 		 * UDP sockets
203 		 */
204 		for (so = udb.so_next; so != &udb; so = so_next) {
205 			so_next = so->so_next;
206 
207 			/*
208 			 * See if it's timed out
209 			 */
210 			if (so->so_expire) {
211 				if (so->so_expire <= curtime) {
212 					udp_detach(so);
213 					continue;
214 				} else
215 					do_slowtimo = 1; /* Let socket expire */
216 			}
217 
218 			/*
219 			 * When UDP packets are received from over the
220 			 * link, they're sendto()'d straight away, so
221 			 * no need for setting for writing
222 			 * Limit the number of packets queued by this session
223 			 * to 4.  Note that even though we try and limit this
224 			 * to 4 packets, the session could have more queued
225 			 * if the packets needed to be fragmented
226 			 * (XXX <= 4 ?)
227 			 */
228 			if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
229 				FD_SET(so->s, readfds);
230 				UPD_NFDS(so->s);
231 			}
232 		}
233 	}
234 
235 	/*
236 	 * Setup timeout to use minimum CPU usage, especially when idle
237 	 */
238 
239 	/*
240 	 * First, see the timeout needed by *timo
241 	 */
242 	timeout.tv_sec = 0;
243 	timeout.tv_usec = -1;
244 	/*
245 	 * If a slowtimo is needed, set timeout to 500ms from the last
246 	 * slow timeout. If a fast timeout is needed, set timeout within
247 	 * 200ms of when it was requested.
248 	 */
249 	if (do_slowtimo) {
250 		/* XXX + 10000 because some select()'s aren't that accurate */
251 		timeout.tv_usec = ((500 - (curtime - last_slowtimo)) * 1000) + 10000;
252 		if (timeout.tv_usec < 0)
253 		   timeout.tv_usec = 0;
254 		else if (timeout.tv_usec > 510000)
255 		   timeout.tv_usec = 510000;
256 
257 		/* Can only fasttimo if we also slowtimo */
258 		if (time_fasttimo) {
259 			tmp_time = (200 - (curtime - time_fasttimo)) * 1000;
260 			if (tmp_time < 0)
261 			   tmp_time = 0;
262 
263 			/* Choose the smallest of the 2 */
264 			if (tmp_time < timeout.tv_usec)
265 			   timeout.tv_usec = (u_int)tmp_time;
266 		}
267 	}
268         *pnfds = nfds;
269 }
270 
slirp_select_poll(fd_set * readfds,fd_set * writefds,fd_set * xfds)271 void slirp_select_poll(fd_set *readfds, fd_set *writefds, fd_set *xfds)
272 {
273     struct socket *so, *so_next;
274     int ret;
275 
276     global_readfds = readfds;
277     global_writefds = writefds;
278     global_xfds = xfds;
279 
280 	/* Update time */
281 	updtime();
282 
283 	/*
284 	 * See if anything has timed out
285 	 */
286 	if (link_up) {
287 		if (time_fasttimo && ((curtime - time_fasttimo) >= 199)) {
288 			tcp_fasttimo();
289 			time_fasttimo = 0;
290 		}
291 		if (do_slowtimo && ((curtime - last_slowtimo) >= 499)) {
292 			ip_slowtimo();
293 			tcp_slowtimo();
294 			last_slowtimo = curtime;
295 		}
296 	}
297 
298 	/*
299 	 * Check sockets
300 	 */
301 	if (link_up) {
302 		/*
303 		 * Check TCP sockets
304 		 */
305 		for (so = tcb.so_next; so != &tcb; so = so_next) {
306 			so_next = so->so_next;
307 
308 			/*
309 			 * FD_ISSET is meaningless on these sockets
310 			 * (and they can crash the program)
311 			 */
312 			if (so->so_state & SS_NOFDREF || so->s == -1)
313 			   continue;
314 
315 			/*
316 			 * Check for URG data
317 			 * This will soread as well, so no need to
318 			 * test for readfds below if this succeeds
319 			 */
320 			if (FD_ISSET(so->s, xfds))
321 			   sorecvoob(so);
322 			/*
323 			 * Check sockets for reading
324 			 */
325 			else if (FD_ISSET(so->s, readfds)) {
326 				/*
327 				 * Check for incoming connections
328 				 */
329 				if (so->so_state & SS_FACCEPTCONN) {
330 					tcp_connect(so);
331 					continue;
332 				} /* else */
333 				ret = soread(so);
334 
335 				/* Output it if we read something */
336 				if (ret > 0)
337 				   tcp_output(sototcpcb(so));
338 			}
339 
340 			/*
341 			 * Check sockets for writing
342 			 */
343 			if (FD_ISSET(so->s, writefds)) {
344 			  /*
345 			   * Check for non-blocking, still-connecting sockets
346 			   */
347 			  if (so->so_state & SS_ISFCONNECTING) {
348 			    /* Connected */
349 			    so->so_state &= ~SS_ISFCONNECTING;
350 
351 			    ret = write(so->s, &ret, 0);
352 			    if (ret < 0) {
353 			      /* XXXXX Must fix, zero bytes is a NOP */
354 			      if (errno == EAGAIN || errno == EWOULDBLOCK ||
355 				  errno == EINPROGRESS || errno == ENOTCONN)
356 				continue;
357 
358 			      /* else failed */
359 			      so->so_state = SS_NOFDREF;
360 			    }
361 			    /* else so->so_state &= ~SS_ISFCONNECTING; */
362 
363 			    /*
364 			     * Continue tcp_input
365 			     */
366 			    tcp_input((struct mbuf *)NULL, sizeof(struct ip), so);
367 			    /* continue; */
368 			  } else
369 			    ret = sowrite(so);
370 			  /*
371 			   * XXXXX If we wrote something (a lot), there
372 			   * could be a need for a window update.
373 			   * In the worst case, the remote will send
374 			   * a window probe to get things going again
375 			   */
376 			}
377 
378 			/*
379 			 * Probe a still-connecting, non-blocking socket
380 			 * to check if it's still alive
381 	 	 	 */
382 #ifdef PROBE_CONN
383 			if (so->so_state & SS_ISFCONNECTING) {
384 			  ret = read(so->s, (char *)&ret, 0);
385 
386 			  if (ret < 0) {
387 			    /* XXX */
388 			    if (errno == EAGAIN || errno == EWOULDBLOCK ||
389 				errno == EINPROGRESS || errno == ENOTCONN)
390 			      continue; /* Still connecting, continue */
391 
392 			    /* else failed */
393 			    so->so_state = SS_NOFDREF;
394 
395 			    /* tcp_input will take care of it */
396 			  } else {
397 			    ret = write(so->s, &ret, 0);
398 			    if (ret < 0) {
399 			      /* XXX */
400 			      if (errno == EAGAIN || errno == EWOULDBLOCK ||
401 				  errno == EINPROGRESS || errno == ENOTCONN)
402 				continue;
403 			      /* else failed */
404 			      so->so_state = SS_NOFDREF;
405 			    } else
406 			      so->so_state &= ~SS_ISFCONNECTING;
407 
408 			  }
409 			  tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
410 			} /* SS_ISFCONNECTING */
411 #endif
412 		}
413 
414 		/*
415 		 * Now UDP sockets.
416 		 * Incoming packets are sent straight away, they're not buffered.
417 		 * Incoming UDP data isn't buffered either.
418 		 */
419 		for (so = udb.so_next; so != &udb; so = so_next) {
420 			so_next = so->so_next;
421 
422 			if (so->s != -1 && FD_ISSET(so->s, readfds)) {
423                             sorecvfrom(so);
424                         }
425 		}
426 	}
427 
428 	/*
429 	 * See if we can start outputting
430 	 */
431 	if (if_queued && link_up)
432 	   if_start();
433 }
434 
435 #define ETH_ALEN 6
436 #define ETH_HLEN 14
437 
438 #define ETH_P_IP	0x0800		/* Internet Protocol packet	*/
439 #define ETH_P_ARP	0x0806		/* Address Resolution packet	*/
440 
441 #define	ARPOP_REQUEST	1		/* ARP request			*/
442 #define	ARPOP_REPLY	2		/* ARP reply			*/
443 
444 struct ethhdr
445 {
446 	unsigned char	h_dest[ETH_ALEN];	/* destination eth addr	*/
447 	unsigned char	h_source[ETH_ALEN];	/* source ether addr	*/
448 	unsigned short	h_proto;		/* packet type ID field	*/
449 };
450 
451 struct arphdr
452 {
453 	unsigned short	ar_hrd;		/* format of hardware address	*/
454 	unsigned short	ar_pro;		/* format of protocol address	*/
455 	unsigned char	ar_hln;		/* length of hardware address	*/
456 	unsigned char	ar_pln;		/* length of protocol address	*/
457 	unsigned short	ar_op;		/* ARP opcode (command)		*/
458 
459 	 /*
460 	  *	 Ethernet looks like this : This bit is variable sized however...
461 	  */
462 	unsigned char		ar_sha[ETH_ALEN];	/* sender hardware address	*/
463 	unsigned char		ar_sip[4];		/* sender IP address		*/
464 	unsigned char		ar_tha[ETH_ALEN];	/* target hardware address	*/
465 	unsigned char		ar_tip[4];		/* target IP address		*/
466 };
467 
arp_input(const uint8_t * pkt,int pkt_len)468 void arp_input(const uint8_t *pkt, int pkt_len)
469 {
470     struct ethhdr *eh = (struct ethhdr *)pkt;
471     struct arphdr *ah = (struct arphdr *)(pkt + ETH_HLEN);
472     uint8_t arp_reply[ETH_HLEN + sizeof(struct arphdr)];
473     struct ethhdr *reh = (struct ethhdr *)arp_reply;
474     struct arphdr *rah = (struct arphdr *)(arp_reply + ETH_HLEN);
475     int ar_op;
476 
477     ar_op = ntohs(ah->ar_op);
478     switch(ar_op) {
479     case ARPOP_REQUEST:
480         if (!memcmp(ah->ar_tip, &special_addr, 3) &&
481             (ah->ar_tip[3] == CTL_DNS || ah->ar_tip[3] == CTL_ALIAS)) {
482 
483             /* XXX: make an ARP request to have the client address */
484             memcpy(client_ethaddr, eh->h_source, ETH_ALEN);
485 
486             /* ARP request for alias/dns mac address */
487             memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
488             memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 1);
489             reh->h_source[5] = ah->ar_tip[3];
490             reh->h_proto = htons(ETH_P_ARP);
491 
492             rah->ar_hrd = htons(1);
493             rah->ar_pro = htons(ETH_P_IP);
494             rah->ar_hln = ETH_ALEN;
495             rah->ar_pln = 4;
496             rah->ar_op = htons(ARPOP_REPLY);
497             memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
498             memcpy(rah->ar_sip, ah->ar_tip, 4);
499             memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
500             memcpy(rah->ar_tip, ah->ar_sip, 4);
501 
502             slirp_output(arp_reply, sizeof(arp_reply));
503         }
504         break;
505     default:
506         break;
507     }
508 }
509 
slirp_input(const uint8_t * pkt,int pkt_len)510 void slirp_input(const uint8_t *pkt, int pkt_len)
511 {
512     struct mbuf *m;
513     int proto;
514 
515     if (pkt_len < ETH_HLEN)
516         return;
517 
518     proto = ntohs(*(uint16_t *)(pkt + 12));
519     switch(proto) {
520     case ETH_P_ARP:
521         arp_input(pkt, pkt_len);
522         break;
523     case ETH_P_IP:
524         m = m_get();
525         if (!m)
526             return;
527         m->m_len = pkt_len;
528         memcpy(m->m_data, pkt, pkt_len);
529 
530         m->m_data += ETH_HLEN;
531         m->m_len -= ETH_HLEN;
532 
533         ip_input(m);
534         break;
535     default:
536         break;
537     }
538 }
539 
540 /* output the IP packet to the ethernet device */
if_encap(const uint8_t * ip_data,int ip_data_len)541 void if_encap(const uint8_t *ip_data, int ip_data_len)
542 {
543     uint8_t buf[1600];
544     struct ethhdr *eh = (struct ethhdr *)buf;
545 
546     if (ip_data_len + ETH_HLEN > sizeof(buf))
547         return;
548 
549     memcpy(eh->h_dest, client_ethaddr, ETH_ALEN);
550     memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 1);
551     eh->h_source[5] = CTL_ALIAS;
552     eh->h_proto = htons(ETH_P_IP);
553     memcpy(buf + sizeof(struct ethhdr), ip_data, ip_data_len);
554     slirp_output(buf, ip_data_len + ETH_HLEN);
555 }
556