Changeset 14964 in vbox for trunk/src/VBox/Devices/Network/slirp
- Timestamp:
- Dec 3, 2008 9:34:37 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 40325
- Location:
- trunk/src/VBox/Devices/Network/slirp
- Files:
-
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Network/slirp/bootp.h
r7809 r14964 93 93 #define DHCP_OPT_LEN 312 94 94 95 struct bootp_t { 96 struct ip ip; 97 struct udphdr udp; 98 uint8_t bp_op; 99 uint8_t bp_htype; 100 uint8_t bp_hlen; 101 uint8_t bp_hops; 102 uint32_t bp_xid; 103 uint16_t bp_secs; 104 uint16_t unused; 95 struct bootp_t 96 { 97 struct ip ip; 98 struct udphdr udp; 99 uint8_t bp_op; 100 uint8_t bp_htype; 101 uint8_t bp_hlen; 102 uint8_t bp_hops; 103 uint32_t bp_xid; 104 uint16_t bp_secs; 105 uint16_t unused; 105 106 struct in_addr bp_ciaddr; 106 107 struct in_addr bp_yiaddr; 107 108 struct in_addr bp_siaddr; 108 109 struct in_addr bp_giaddr; 109 uint8_t bp_hwaddr[16];110 uint8_t bp_sname[64];111 uint8_t bp_file[128];112 uint8_t bp_vend[DHCP_OPT_LEN];110 uint8_t bp_hwaddr[16]; 111 uint8_t bp_sname[64]; 112 uint8_t bp_file[128]; 113 uint8_t bp_vend[DHCP_OPT_LEN]; 113 114 }; 114 115 -
trunk/src/VBox/Devices/Network/slirp/cksum.c
r14470 r14964 47 47 48 48 #define ADDCARRY(x) (x > 65535 ? x -= 65535 : x) 49 #define REDUCE { l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}49 #define REDUCE { l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum); } 50 50 51 51 int cksum(struct mbuf *m, int len) 52 52 { 53 54 55 56 53 register u_int16_t *w; 54 register int sum = 0; 55 register int mlen = 0; 56 int byte_swapped = 0; 57 57 58 union { 59 u_int8_t c[2]; 60 u_int16_t s; 61 } s_util; 62 union { 63 u_int16_t s[2]; 64 u_int32_t l; 65 } l_util; 58 union 59 { 60 u_int8_t c[2]; 61 u_int16_t s; 62 } s_util; 63 union 64 { 65 u_int16_t s[2]; 66 u_int32_t l; 67 } l_util; 66 68 67 if (m->m_len == 0) 68 goto cont; 69 w = mtod(m, u_int16_t *); 69 if (m->m_len == 0) 70 goto cont; 71 w = mtod(m, u_int16_t *); 72 73 mlen = m->m_len; 70 74 71 mlen = m->m_len; 75 if (len < mlen) 76 mlen = len; 77 len -= mlen; 78 /* 79 * Force to even boundary. 80 */ 81 if ((1 & (long) w) && (mlen > 0)) 82 { 83 REDUCE; 84 sum <<= 8; 85 s_util.c[0] = *(u_int8_t *)w; 86 w = (u_int16_t *)((int8_t *)w + 1); 87 mlen--; 88 byte_swapped = 1; 89 } 90 /* 91 * Unroll the loop to make overhead from 92 * branches &c small. 93 */ 94 while ((mlen -= 32) >= 0) 95 { 96 sum += w[ 0]; sum += w[ 1]; sum += w[ 2]; sum += w[ 3]; 97 sum += w[ 4]; sum += w[ 5]; sum += w[ 6]; sum += w[ 7]; 98 sum += w[ 8]; sum += w[ 9]; sum += w[10]; sum += w[11]; 99 sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; 100 w += 16; 101 } 102 mlen += 32; 103 while ((mlen -= 8) >= 0) 104 { 105 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 106 w += 4; 107 } 108 mlen += 8; 109 if (mlen == 0 && byte_swapped == 0) 110 goto cont; 111 REDUCE; 112 while ((mlen -= 2) >= 0) 113 { 114 sum += *w++; 115 } 72 116 73 if (len < mlen) 74 mlen = len; 75 len -= mlen; 76 /* 77 * Force to even boundary. 78 */ 79 if ((1 & (long) w) && (mlen > 0)) { 80 REDUCE; 81 sum <<= 8; 82 s_util.c[0] = *(u_int8_t *)w; 83 w = (u_int16_t *)((int8_t *)w + 1); 84 mlen--; 85 byte_swapped = 1; 117 if (byte_swapped) 118 { 119 REDUCE; 120 sum <<= 8; 121 byte_swapped = 0; 122 if (mlen == -1) 123 { 124 s_util.c[1] = *(u_int8_t *)w; 125 sum += s_util.s; 126 mlen = 0; 86 127 } 87 /* 88 * Unroll the loop to make overhead from 89 * branches &c small. 90 */ 91 while ((mlen -= 32) >= 0) { 92 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 93 sum += w[4]; sum += w[5]; sum += w[6]; sum += w[7]; 94 sum += w[8]; sum += w[9]; sum += w[10]; sum += w[11]; 95 sum += w[12]; sum += w[13]; sum += w[14]; sum += w[15]; 96 w += 16; 97 } 98 mlen += 32; 99 while ((mlen -= 8) >= 0) { 100 sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; 101 w += 4; 102 } 103 mlen += 8; 104 if (mlen == 0 && byte_swapped == 0) 105 goto cont; 106 REDUCE; 107 while ((mlen -= 2) >= 0) { 108 sum += *w++; 109 } 110 111 if (byte_swapped) { 112 REDUCE; 113 sum <<= 8; 114 byte_swapped = 0; 115 if (mlen == -1) { 116 s_util.c[1] = *(u_int8_t *)w; 117 sum += s_util.s; 118 mlen = 0; 119 } else 120 121 mlen = -1; 122 } else if (mlen == -1) 123 s_util.c[0] = *(u_int8_t *)w; 128 else 129 mlen = -1; 130 } 131 else if (mlen == -1) 132 s_util.c[0] = *(u_int8_t *)w; 124 133 125 134 cont: 126 135 #ifdef DEBUG 127 if (len) { 128 DEBUG_ERROR((dfd, "cksum: out of data\n")); 129 DEBUG_ERROR((dfd, " len = %d\n", len)); 130 } 136 if (len) 137 { 138 DEBUG_ERROR((dfd, "cksum: out of data\n")); 139 DEBUG_ERROR((dfd, " len = %d\n", len)); 140 } 131 141 #endif 132 if (mlen == -1) { 133 /* The last mbuf has odd # of bytes. Follow the 134 standard (the odd byte may be shifted left by 8 bits 135 or not as determined by endian-ness of the machine) */ 136 s_util.c[1] = 0; 137 sum += s_util.s; 138 } 139 REDUCE; 140 return (~sum & 0xffff); 142 if (mlen == -1) 143 { 144 /* The last mbuf has odd # of bytes. Follow the 145 standard (the odd byte may be shifted left by 8 bits 146 or not as determined by endian-ness of the machine) */ 147 s_util.c[1] = 0; 148 sum += s_util.s; 149 } 150 REDUCE; 151 return (~sum & 0xffff); 141 152 } -
trunk/src/VBox/Devices/Network/slirp/icmp_var.h
r1076 r14964 42 42 * of the internet control message protocol. 43 43 */ 44 struct icmpstat_t { 44 struct icmpstat_t 45 { 45 46 /* statistics related to input messages processed */ 46 47 48 49 50 51 47 u_long icps_received; /* #ICMP packets received */ 48 u_long icps_tooshort; /* packet < ICMP_MINLEN */ 49 u_long icps_checksum; /* bad checksum */ 50 u_long icps_notsupp; /* #ICMP packets not supported */ 51 u_long icps_badtype; /* #with bad type feild */ 52 u_long icps_reflect; /* number of responses */ 52 53 }; 53 54 -
trunk/src/VBox/Devices/Network/slirp/if.h
r14476 r14964 17 17 #undef if_mtu 18 18 extern int if_mtu; 19 extern int if_mru; /* MTU and MRU */19 extern int if_mru; /* MTU and MRU */ 20 20 extern int if_comp; /* Flags for compression */ 21 21 extern int if_maxlinkhdr; … … 24 24 * (to prevent allocing too many mbufs) */ 25 25 26 extern struct mbuf if_fastq; 27 extern struct mbuf if_batchq; 26 extern struct mbuf if_fastq; /* fast queue (for interactive data) */ 27 extern struct mbuf if_batchq; /* queue for non-interactive data */ 28 28 extern struct mbuf *next_m; 29 29 -
trunk/src/VBox/Devices/Network/slirp/ip_output.c
r14470 r14964 55 55 ip_output(PNATState pData, struct socket *so, struct mbuf *m0) 56 56 { 57 register struct ip *ip; 58 register struct mbuf *m = m0; 59 register int hlen = sizeof(struct ip ); 60 int len, off, error = 0; 61 62 DEBUG_CALL("ip_output"); 63 DEBUG_ARG("so = %lx", (long)so); 64 DEBUG_ARG("m0 = %lx", (long)m0); 65 66 /* We do no options */ 67 /* if (opt) { 68 * m = ip_insertoptions(m, opt, &len); 69 * hlen = len; 70 * } 71 */ 72 ip = mtod(m, struct ip *); 73 /* 74 * Fill in IP header. 75 */ 76 ip->ip_v = IPVERSION; 77 ip->ip_off &= IP_DF; 78 ip->ip_id = htons(ip_currid++); 79 ip->ip_hl = hlen >> 2; 80 ipstat.ips_localout++; 81 82 /* 83 * Verify that we have any chance at all of being able to queue 84 * the packet or packet fragments 85 */ 86 /* XXX Hmmm... */ 87 /* if (if_queued > if_thresh && towrite <= 0) { 88 * error = ENOBUFS; 89 * goto bad; 90 * } 91 */ 92 93 /* 94 * If small enough for interface, can just send directly. 95 */ 96 if ((u_int16_t)ip->ip_len <= if_mtu) { 97 ip->ip_len = htons((u_int16_t)ip->ip_len); 98 ip->ip_off = htons((u_int16_t)ip->ip_off); 99 ip->ip_sum = 0; 100 ip->ip_sum = cksum(m, hlen); 101 102 if_output(pData, so, m); 103 goto done; 104 } 105 106 /* 107 * Too large for interface; fragment if possible. 108 * Must be able to put at least 8 bytes per fragment. 109 */ 110 if (ip->ip_off & IP_DF) { 111 error = -1; 112 ipstat.ips_cantfrag++; 113 goto bad; 114 } 115 116 len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */ 117 if (len < 8) { 118 error = -1; 119 goto bad; 120 } 57 register struct ip *ip; 58 register struct mbuf *m = m0; 59 register int hlen = sizeof(struct ip ); 60 int len, off, error = 0; 61 62 DEBUG_CALL("ip_output"); 63 DEBUG_ARG("so = %lx", (long)so); 64 DEBUG_ARG("m0 = %lx", (long)m0); 65 66 #if 0 /* We do no options */ 67 if (opt) 68 { 69 m = ip_insertoptions(m, opt, &len); 70 hlen = len; 71 } 72 #endif 73 ip = mtod(m, struct ip *); 74 /* 75 * Fill in IP header. 76 */ 77 ip->ip_v = IPVERSION; 78 ip->ip_off &= IP_DF; 79 ip->ip_id = htons(ip_currid++); 80 ip->ip_hl = hlen >> 2; 81 ipstat.ips_localout++; 82 83 /* 84 * Verify that we have any chance at all of being able to queue 85 * the packet or packet fragments 86 */ 87 #if 0 /* XXX Hmmm... */ 88 if (if_queued > if_thresh && towrite <= 0) 89 { 90 error = ENOBUFS; 91 goto bad; 92 } 93 #endif 94 95 /* 96 * If small enough for interface, can just send directly. 97 */ 98 if ((u_int16_t)ip->ip_len <= if_mtu) 99 { 100 ip->ip_len = htons((u_int16_t)ip->ip_len); 101 ip->ip_off = htons((u_int16_t)ip->ip_off); 102 ip->ip_sum = 0; 103 ip->ip_sum = cksum(m, hlen); 104 105 if_output(pData, so, m); 106 goto done; 107 } 108 109 /* 110 * Too large for interface; fragment if possible. 111 * Must be able to put at least 8 bytes per fragment. 112 */ 113 if (ip->ip_off & IP_DF) 114 { 115 error = -1; 116 ipstat.ips_cantfrag++; 117 goto bad; 118 } 119 120 len = (if_mtu - hlen) &~ 7; /* ip databytes per packet */ 121 if (len < 8) 122 { 123 error = -1; 124 goto bad; 125 } 121 126 122 127 { … … 130 135 m0 = m; 131 136 mhlen = sizeof (struct ip); 132 for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) { 133 register struct ip *mhip; 134 m = m_get(pData); 135 if (m == 0) { 136 error = -1; 137 ipstat.ips_odropped++; 138 goto sendorfree; 139 } 140 m->m_data += if_maxlinkhdr; 141 mhip = mtod(m, struct ip *); 142 *mhip = *ip; 143 144 /* No options */ 145 /* if (hlen > sizeof (struct ip)) { 146 * mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 147 * mhip->ip_hl = mhlen >> 2; 148 * } 149 */ 150 m->m_len = mhlen; 151 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); 152 if (ip->ip_off & IP_MF) 153 mhip->ip_off |= IP_MF; 154 if (off + len >= (u_int16_t)ip->ip_len) 155 len = (u_int16_t)ip->ip_len - off; 156 else 157 mhip->ip_off |= IP_MF; 158 mhip->ip_len = htons((u_int16_t)(len + mhlen)); 159 160 if (m_copy(m, m0, off, len) < 0) { 161 error = -1; 162 goto sendorfree; 163 } 164 165 mhip->ip_off = htons((u_int16_t)mhip->ip_off); 166 mhip->ip_sum = 0; 167 mhip->ip_sum = cksum(m, mhlen); 168 *mnext = m; 169 mnext = &m->m_nextpkt; 170 ipstat.ips_ofragments++; 137 for (off = hlen + len; off < (u_int16_t)ip->ip_len; off += len) 138 { 139 register struct ip *mhip; 140 m = m_get(pData); 141 if (m == 0) 142 { 143 error = -1; 144 ipstat.ips_odropped++; 145 goto sendorfree; 146 } 147 m->m_data += if_maxlinkhdr; 148 mhip = mtod(m, struct ip *); 149 *mhip = *ip; 150 151 #if 0 /* No options */ 152 if (hlen > sizeof (struct ip)) 153 { 154 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip); 155 mhip->ip_hl = mhlen >> 2; 156 } 157 #endif 158 m->m_len = mhlen; 159 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF); 160 if (ip->ip_off & IP_MF) 161 mhip->ip_off |= IP_MF; 162 if (off + len >= (u_int16_t)ip->ip_len) 163 len = (u_int16_t)ip->ip_len - off; 164 else 165 mhip->ip_off |= IP_MF; 166 mhip->ip_len = htons((u_int16_t)(len + mhlen)); 167 168 if (m_copy(m, m0, off, len) < 0) 169 { 170 error = -1; 171 goto sendorfree; 172 } 173 174 mhip->ip_off = htons((u_int16_t)mhip->ip_off); 175 mhip->ip_sum = 0; 176 mhip->ip_sum = cksum(m, mhlen); 177 *mnext = m; 178 mnext = &m->m_nextpkt; 179 ipstat.ips_ofragments++; 171 180 } 172 181 /* … … 180 189 ip->ip_sum = 0; 181 190 ip->ip_sum = cksum(m, hlen); 191 182 192 sendorfree: 183 for (m = m0; m; m = m0) { 184 m0 = m->m_nextpkt; 185 m->m_nextpkt = 0; 186 if (error == 0) 187 if_output(pData, so, m); 188 else 189 m_freem(pData, m); 193 for (m = m0; m; m = m0) 194 { 195 m0 = m->m_nextpkt; 196 m->m_nextpkt = 0; 197 if (error == 0) 198 if_output(pData, so, m); 199 else 200 m_freem(pData, m); 190 201 } 191 202 192 203 if (error == 0) 193 204 ipstat.ips_fragmented++; 194 205 } 195 206 196 207 done: 197 208 return (error); 198 209 199 210 bad: 200 201 211 m_freem(pData, m0); 212 goto done; 202 213 } -
trunk/src/VBox/Devices/Network/slirp/libslirp.h
r14391 r14964 2 2 #define _LIBSLIRP_H 3 3 4 #ifdef _WIN325 # include <winsock2.h>6 # ifdef __cplusplus4 #ifdef RT_OS_WINDOWS 5 # include <winsock2.h> 6 # ifdef __cplusplus 7 7 extern "C" { 8 # endif8 # endif 9 9 int inet_aton(const char *cp, struct in_addr *ia); 10 # ifdef __cplusplus10 # ifdef __cplusplus 11 11 } 12 # endif12 # endif 13 13 #else 14 # ifdef RT_OS_OS2 /* temporary workaround, see ticket #127 */15 # include <sys/time.h>16 # endif17 # include <sys/select.h>18 # include <arpa/inet.h>14 # ifdef RT_OS_OS2 /* temporary workaround, see ticket #127 */ 15 # include <sys/time.h> 16 # endif 17 # include <sys/select.h> 18 # include <arpa/inet.h> 19 19 #endif 20 20 -
trunk/src/VBox/Devices/Network/slirp/main.h
r1076 r14964 10 10 #endif 11 11 12 #define TOWRITEMAX 51213 14 15 /*16 * Get the difference in 2 times from updtim()17 * Allow for wraparound times, "just in case"18 * x is the greater of the 2 (current time) and y is19 * what it's being compared against.20 */21 #define TIME_DIFF(x,y) (x)-(y) < 0 ? ~0-(y)+(x) : (x)-(y)22 23 24 #define PROTO_SLIP 0x125 #ifdef USE_PPP26 #define PROTO_PPP 0x227 #endif28 29 12 void if_encap(PNATState pData, const uint8_t *ip_data, int ip_data_len); -
trunk/src/VBox/Devices/Network/slirp/mbuf.c
r14470 r14964 22 22 m_init(PNATState pData) 23 23 { 24 25 26 27 24 m_freelist.m_next = m_freelist.m_prev = &m_freelist; 25 m_usedlist.m_next = m_usedlist.m_prev = &m_usedlist; 26 mbuf_alloced = 0; 27 msize_init(pData); 28 28 } 29 29 … … 31 31 msize_init(PNATState pData) 32 32 { 33 34 35 36 37 msize = (if_mtu>if_mru?if_mtu:if_mru) +38 33 /* 34 * Find a nice value for msize 35 * XXX if_maxlinkhdr already in mtu 36 */ 37 msize = (if_mtu>if_mru ? if_mtu : if_mru) 38 + if_maxlinkhdr + sizeof(struct m_hdr ) + 6; 39 39 } 40 40 … … 50 50 m_get(PNATState pData) 51 51 { 52 register struct mbuf *m; 53 int flags = 0; 54 55 DEBUG_CALL("m_get"); 56 57 if (m_freelist.m_next == &m_freelist) { 58 m = (struct mbuf *)malloc(msize); 59 if (m == NULL) goto end_error; 60 mbuf_alloced++; 61 if (mbuf_alloced > mbuf_thresh) 62 flags = M_DOFREE; 63 if (mbuf_alloced > mbuf_max) 64 mbuf_max = mbuf_alloced; 65 } else { 66 m = m_freelist.m_next; 67 remque(pData, m); 68 } 69 70 /* Insert it in the used list */ 71 insque(pData, m,&m_usedlist); 72 m->m_flags = (flags | M_USEDLIST); 73 74 /* Initialise it */ 75 m->m_size = msize - sizeof(struct m_hdr); 76 m->m_data = m->m_dat; 77 m->m_len = 0; 78 m->m_nextpkt = 0; 79 m->m_prevpkt = 0; 52 register struct mbuf *m; 53 int flags = 0; 54 55 DEBUG_CALL("m_get"); 56 57 if (m_freelist.m_next == &m_freelist) 58 { 59 m = (struct mbuf *)malloc(msize); 60 if (m == NULL) goto 61 end_error; 62 mbuf_alloced++; 63 if (mbuf_alloced > mbuf_thresh) 64 flags = M_DOFREE; 65 if (mbuf_alloced > mbuf_max) 66 mbuf_max = mbuf_alloced; 67 } 68 else 69 { 70 m = m_freelist.m_next; 71 remque(pData, m); 72 } 73 74 /* Insert it in the used list */ 75 insque(pData, m, &m_usedlist); 76 m->m_flags = (flags | M_USEDLIST); 77 78 /* Initialise it */ 79 m->m_size = msize - sizeof(struct m_hdr); 80 m->m_data = m->m_dat; 81 m->m_len = 0; 82 m->m_nextpkt = 0; 83 m->m_prevpkt = 0; 84 80 85 end_error: 81 82 86 DEBUG_ARG("m = %lx", (long )m); 87 return m; 83 88 } 84 89 … … 87 92 { 88 93 89 DEBUG_CALL("m_free"); 90 DEBUG_ARG("m = %lx", (long )m); 91 92 if(m) { 94 DEBUG_CALL("m_free"); 95 DEBUG_ARG("m = %lx", (long )m); 96 97 if(m) 98 { 93 99 /* Remove from m_usedlist */ 94 100 if (m->m_flags & M_USEDLIST) 95 remque(pData, m);101 remque(pData, m); 96 102 97 103 /* If it's M_EXT, free() it */ 98 104 if (m->m_flags & M_EXT) 99 free(m->m_ext);105 free(m->m_ext); 100 106 101 107 /* 102 108 * Either free() it or put it on the free list 103 109 */ 104 if (m->m_flags & M_DOFREE) { 105 u32ptr_done(pData, ptr_to_u32(pData, m), m); 106 free(m); 107 mbuf_alloced--; 108 } else if ((m->m_flags & M_FREELIST) == 0) { 109 insque(pData, m,&m_freelist); 110 m->m_flags = M_FREELIST; /* Clobber other flags */ 111 } 112 } /* if(m) */ 110 if (m->m_flags & M_DOFREE) 111 { 112 u32ptr_done(pData, ptr_to_u32(pData, m), m); 113 free(m); 114 mbuf_alloced--; 115 } 116 else if ((m->m_flags & M_FREELIST) == 0) 117 { 118 insque(pData, m,&m_freelist); 119 m->m_flags = M_FREELIST; /* Clobber other flags */ 120 } 121 } /* if(m) */ 113 122 } 114 123 … … 121 130 m_cat(PNATState pData, register struct mbuf *m, register struct mbuf *n) 122 131 { 123 124 125 126 127 128 129 130 131 132 132 /* 133 * If there's no room, realloc 134 */ 135 if (M_FREEROOM(m) < n->m_len) 136 m_inc(m,m->m_size+MINCSIZE); 137 138 memcpy(m->m_data+m->m_len, n->m_data, n->m_len); 139 m->m_len += n->m_len; 140 141 m_free(pData, n); 133 142 } 134 143 … … 136 145 /* make m size bytes large */ 137 146 void 138 m_inc(m, size) 139 struct mbuf *m; 140 int size; 141 { 142 int datasize; 143 144 /* some compiles throw up on gotos. This one we can fake. */ 145 if(m->m_size>size) return; 146 147 if (m->m_flags & M_EXT) { 148 datasize = m->m_data - m->m_ext; 149 m->m_ext = (char *)realloc(m->m_ext,size); 150 /* if (m->m_ext == NULL) 151 * return (struct mbuf *)NULL; 152 */ 153 m->m_data = m->m_ext + datasize; 154 } else { 155 char *dat; 156 datasize = m->m_data - m->m_dat; 157 dat = (char *)malloc(size); 158 /* if (dat == NULL) 159 * return (struct mbuf *)NULL; 160 */ 161 memcpy(dat, m->m_dat, m->m_size); 162 163 m->m_ext = dat; 164 m->m_data = m->m_ext + datasize; 165 m->m_flags |= M_EXT; 166 } 167 168 m->m_size = size; 169 170 } 171 172 173 174 void 175 m_adj(m, len) 176 struct mbuf *m; 177 int len; 178 { 179 if (m == NULL) 180 return; 181 if (len >= 0) { 182 /* Trim from head */ 183 m->m_data += len; 184 m->m_len -= len; 185 } else { 186 /* Trim from tail */ 187 len = -len; 188 m->m_len -= len; 189 } 147 m_inc(struct mbuf *m, int size) 148 { 149 int datasize; 150 151 /* some compiles throw up on gotos. This one we can fake. */ 152 if (m->m_size>size) 153 return; 154 155 if (m->m_flags & M_EXT) 156 { 157 datasize = m->m_data - m->m_ext; 158 m->m_ext = (char *)realloc(m->m_ext,size); 159 #if 0 160 if (m->m_ext == NULL) 161 return (struct mbuf *)NULL; 162 #endif 163 m->m_data = m->m_ext + datasize; 164 } 165 else 166 { 167 char *dat; 168 datasize = m->m_data - m->m_dat; 169 dat = (char *)malloc(size); 170 #if 0 171 if (dat == NULL) 172 return (struct mbuf *)NULL; 173 #endif 174 memcpy(dat, m->m_dat, m->m_size); 175 176 m->m_ext = dat; 177 m->m_data = m->m_ext + datasize; 178 m->m_flags |= M_EXT; 179 } 180 181 m->m_size = size; 182 } 183 184 185 void 186 m_adj(struct mbuf *m, int len) 187 { 188 if (m == NULL) 189 return; 190 if (len >= 0) 191 { 192 /* Trim from head */ 193 m->m_data += len; 194 m->m_len -= len; 195 } 196 else 197 { 198 /* Trim from tail */ 199 len = -len; 200 m->m_len -= len; 201 } 190 202 } 191 203 … … 195 207 */ 196 208 int 197 m_copy(n, m, off, len) 198 struct mbuf *n, *m; 199 int off, len; 200 { 201 if (len > M_FREEROOM(n)) 202 return -1; 203 204 memcpy((n->m_data + n->m_len), (m->m_data + off), len); 205 n->m_len += len; 206 return 0; 209 m_copy(struct mbuf *n, struct mbuf *m, int off, int len) 210 { 211 if (len > M_FREEROOM(n)) 212 return -1; 213 214 memcpy((n->m_data + n->m_len), (m->m_data + off), len); 215 n->m_len += len; 216 return 0; 207 217 } 208 218 … … 216 226 dtom(PNATState pData, void *dat) 217 227 { 218 struct mbuf *m; 219 220 DEBUG_CALL("dtom"); 221 DEBUG_ARG("dat = %lx", (long )dat); 222 223 /* bug corrected for M_EXT buffers */ 224 for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) { 225 if (m->m_flags & M_EXT) { 226 if( (char *)dat>=m->m_ext && (char *)dat<(m->m_ext + m->m_size) ) 227 return m; 228 } else { 229 if( (char *)dat >= m->m_dat && (char *)dat<(m->m_dat + m->m_size) ) 230 return m; 231 } 232 } 233 234 DEBUG_ERROR((dfd, "dtom failed")); 235 236 return (struct mbuf *)0; 237 } 238 228 struct mbuf *m; 229 230 DEBUG_CALL("dtom"); 231 DEBUG_ARG("dat = %lx", (long )dat); 232 233 /* bug corrected for M_EXT buffers */ 234 for (m = m_usedlist.m_next; m != &m_usedlist; m = m->m_next) 235 { 236 if (m->m_flags & M_EXT) 237 { 238 if ( (char *)dat >= m->m_ext 239 && (char *)dat < (m->m_ext + m->m_size)) 240 return m; 241 } 242 else 243 { 244 if ( (char *)dat >= m->m_dat 245 && (char *)dat < (m->m_dat + m->m_size)) 246 return m; 247 } 248 } 249 250 DEBUG_ERROR((dfd, "dtom failed")); 251 252 return (struct mbuf *)0; 253 } -
trunk/src/VBox/Devices/Network/slirp/mbuf.h
r14470 r14964 61 61 /* XXX should union some of these! */ 62 62 /* header at beginning of each mbuf: */ 63 struct m_hdr { 64 struct mbuf *mh_next; /* Linked list of mbufs */ 65 struct mbuf *mh_prev; 66 struct mbuf *mh_nextpkt; /* Next packet in queue/record */ 67 struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */ 68 int mh_flags; /* Misc flags */ 63 struct m_hdr 64 { 65 struct mbuf *mh_next; /* Linked list of mbufs */ 66 struct mbuf *mh_prev; 67 struct mbuf *mh_nextpkt; /* Next packet in queue/record */ 68 struct mbuf *mh_prevpkt; /* Flags aren't used in the output queue */ 69 int mh_flags; /* Misc flags */ 69 70 70 int mh_size;/* Size of data */71 71 int mh_size; /* Size of data */ 72 struct socket *mh_so; 72 73 73 caddr_t mh_data;/* Location of data */74 int mh_len;/* Amount of data in this mbuf */74 caddr_t mh_data; /* Location of data */ 75 int mh_len; /* Amount of data in this mbuf */ 75 76 #ifdef VBOX_WITH_BSD_REASS 76 void *header;/*XXX: in real BSD sources this field lays in pkthdr structure*/77 void *header; /*XXX: in real BSD sources this field lays in pkthdr structure*/ 77 78 #endif 78 79 }; … … 92 93 #define M_TRAILINGSPACE M_FREEROOM 93 94 94 struct mbuf { 95 struct m_hdr m_hdr; 96 union M_dat { 97 char m_dat_[1]; /* ANSI don't like 0 sized arrays */ 98 char *m_ext_; 99 } M_dat; 95 struct mbuf 96 { 97 struct m_hdr m_hdr; 98 union M_dat 99 { 100 char m_dat_[1]; /* ANSI don't like 0 sized arrays */ 101 char *m_ext_; 102 } M_dat; 100 103 }; 101 104 … … 129 132 #endif /* VBOX_WITH_BSD_REASS */ 130 133 131 /*132 * Mbuf statistics. XXX133 */134 135 struct mbstat {136 int mbs_alloced; /* Number of mbufs allocated */137 138 };139 140 extern struct mbstat mbstat;141 134 extern int mbuf_alloced; 142 135 extern struct mbuf m_freelist, m_usedlist; -
trunk/src/VBox/Devices/Network/slirp/misc.c
r14638 r14964 11 11 #ifndef HAVE_INET_ATON 12 12 int 13 inet_aton(cp, ia) 14 const char *cp; 15 struct in_addr *ia; 13 inet_aton(const char *cp, struct in_addr *ia) 16 14 { 17 18 19 20 21 15 u_int32_t addr = inet_addr(cp); 16 if (addr == 0xffffffff) 17 return 0; 18 ia->s_addr = addr; 19 return 1; 22 20 } 23 21 #endif … … 29 27 getouraddr(PNATState pData) 30 28 { 31 29 our_addr.s_addr = loopback_addr.s_addr; 32 30 } 33 31 34 32 #if SIZEOF_CHAR_P == 8 && !defined(VBOX_WITH_BSD_REASS) 35 33 36 struct quehead_32 { 37 u_int32_t qh_link; 38 u_int32_t qh_rlink; 34 struct quehead_32 35 { 36 u_int32_t qh_link; 37 u_int32_t qh_rlink; 39 38 }; 40 39 … … 42 41 insque_32(PNATState pData, void *a, void *b) 43 42 { 44 45 46 43 register struct quehead_32 *element = (struct quehead_32 *) a; 44 register struct quehead_32 *head = (struct quehead_32 *) b; 45 struct quehead_32 *link = u32_to_ptr(pData, head->qh_link, struct quehead_32 *); 47 46 48 49 50 51 47 element->qh_link = head->qh_link; 48 element->qh_rlink = ptr_to_u32(pData, head); 49 Assert(link->qh_rlink == element->qh_rlink); 50 link->qh_rlink = head->qh_link = ptr_to_u32(pData, element); 52 51 } 53 52 … … 55 54 remque_32(PNATState pData, void *a) 56 55 { 57 58 59 56 register struct quehead_32 *element = (struct quehead_32 *) a; 57 struct quehead_32 *link = u32_to_ptr(pData, element->qh_link, struct quehead_32 *); 58 struct quehead_32 *rlink = u32_to_ptr(pData, element->qh_rlink, struct quehead_32 *); 60 59 61 62 63 64 60 u32ptr_done(pData, link->qh_rlink, element); 61 link->qh_rlink = element->qh_rlink; 62 rlink->qh_link = element->qh_link; 63 element->qh_rlink = 0; 65 64 } 66 65 67 66 #endif /* SIZEOF_CHAR_P == 8 && !VBOX_WITH_BSD_REASS */ 68 67 69 struct quehead { 70 struct quehead *qh_link; 71 struct quehead *qh_rlink; 68 struct quehead 69 { 70 struct quehead *qh_link; 71 struct quehead *qh_rlink; 72 72 }; 73 73 … … 75 75 insque(PNATState pData, void *a, void *b) 76 76 { 77 register struct quehead *element = (struct quehead *) a; 78 register struct quehead *head = (struct quehead *) b; 79 element->qh_link = head->qh_link; 80 head->qh_link = (struct quehead *)element; 81 element->qh_rlink = (struct quehead *)head; 82 ((struct quehead *)(element->qh_link))->qh_rlink 83 = (struct quehead *)element; 77 register struct quehead *element = (struct quehead *) a; 78 register struct quehead *head = (struct quehead *) b; 79 element->qh_link = head->qh_link; 80 head->qh_link = (struct quehead *)element; 81 element->qh_rlink = (struct quehead *)head; 82 ((struct quehead *)(element->qh_link))->qh_rlink = (struct quehead *)element; 84 83 } 85 84 … … 87 86 remque(PNATState pData, void *a) 88 87 { 89 register struct quehead *element = (struct quehead *) a; 90 ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; 91 ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link; 92 element->qh_rlink = NULL; 93 /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */ 94 } 95 96 /* #endif */ 97 98 99 int 100 add_exec(ex_ptr, do_pty, exec, addr, port) 101 struct ex_list **ex_ptr; 102 int do_pty; 103 char *exec; 104 int addr; 105 int port; 106 { 107 struct ex_list *tmp_ptr; 108 109 /* First, check if the port is "bound" */ 110 for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) { 111 if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr) 112 return -1; 113 } 114 115 tmp_ptr = *ex_ptr; 116 *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list)); 117 (*ex_ptr)->ex_fport = port; 118 (*ex_ptr)->ex_addr = addr; 119 (*ex_ptr)->ex_pty = do_pty; 120 (*ex_ptr)->ex_exec = strdup(exec); 121 (*ex_ptr)->ex_next = tmp_ptr; 122 return 0; 123 } 124 125 #ifndef HAVE_STRERROR 126 127 /* 128 * For systems with no strerror 129 */ 130 131 extern int sys_nerr; 132 extern char *sys_errlist[]; 133 134 char * 135 strerror(error) 136 int error; 137 { 138 if (error < sys_nerr) 139 return sys_errlist[error]; 140 else 141 return "Unknown error."; 142 } 143 144 #endif 145 146 147 #ifndef HAVE_STRDUP 148 char * 149 strdup(str) 150 const char *str; 151 { 152 char *bptr; 153 154 bptr = (char *)malloc(strlen(str)+1); 155 strcpy(bptr, str); 156 157 return bptr; 158 } 159 #endif 160 161 #ifdef BAD_SPRINTF 162 163 #undef vsprintf 164 #undef sprintf 165 166 /* 167 * Some BSD-derived systems have a sprintf which returns char * 168 */ 169 170 int 171 vsprintf_len(string, format, args) 172 char *string; 173 const char *format; 174 va_list args; 175 { 176 vsprintf(string, format, args); 177 return strlen(string); 88 register struct quehead *element = (struct quehead *) a; 89 ((struct quehead *)(element->qh_link))->qh_rlink = element->qh_rlink; 90 ((struct quehead *)(element->qh_rlink))->qh_link = element->qh_link; 91 element->qh_rlink = NULL; 92 /* element->qh_link = NULL; TCP FIN1 crashes if you do this. Why ? */ 178 93 } 179 94 180 95 int 181 #ifdef __STDC__ 182 sprintf_len(char *string, const char *format, ...) 183 #else 184 sprintf_len(va_alist) va_dcl 185 #endif 96 add_exec(struct ex_list **ex_ptr, int do_pty, char *exec, int addr, int port) 186 97 { 187 va_list args; 188 #ifdef __STDC__ 189 va_start(args, format); 190 #else 191 char *string; 192 char *format; 193 va_start(args); 194 string = va_arg(args, char *); 195 format = va_arg(args, char *); 196 #endif 197 vsprintf(string, format, args); 198 return strlen(string); 98 struct ex_list *tmp_ptr; 99 100 /* First, check if the port is "bound" */ 101 for (tmp_ptr = *ex_ptr; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) 102 { 103 if (port == tmp_ptr->ex_fport && addr == tmp_ptr->ex_addr) 104 return -1; 105 } 106 107 tmp_ptr = *ex_ptr; 108 *ex_ptr = (struct ex_list *)malloc(sizeof(struct ex_list)); 109 (*ex_ptr)->ex_fport = port; 110 (*ex_ptr)->ex_addr = addr; 111 (*ex_ptr)->ex_pty = do_pty; 112 (*ex_ptr)->ex_exec = strdup(exec); 113 (*ex_ptr)->ex_next = tmp_ptr; 114 return 0; 199 115 } 200 116 201 #endif202 203 void204 u_sleep(usec)205 int usec;206 {207 struct timeval t;208 fd_set fdset;209 210 FD_ZERO(&fdset);211 212 t.tv_sec = 0;213 t.tv_usec = usec * 1000;214 215 select(0, &fdset, &fdset, &fdset, &t);216 }217 117 218 118 /* 219 119 * Set fd blocking and non-blocking 220 120 */ 221 222 121 void 223 fd_nonblock(fd) 224 int fd; 122 fd_nonblock(int fd) 225 123 { 226 124 #ifdef FIONBIO 227 125 int opt = 1; 228 126 229 127 ioctlsocket(fd, FIONBIO, &opt); 230 128 #else 231 129 int opt; 232 130 233 234 235 131 opt = fcntl(fd, F_GETFL, 0); 132 opt |= O_NONBLOCK; 133 fcntl(fd, F_SETFL, opt); 236 134 #endif 237 135 } 238 136 239 137 void 240 fd_block(fd) 241 int fd; 138 fd_block(int fd) 242 139 { 243 140 #ifdef FIONBIO 244 141 int opt = 0; 245 142 246 143 ioctlsocket(fd, FIONBIO, &opt); 247 144 #else 248 145 int opt; 249 146 250 251 252 147 opt = fcntl(fd, F_GETFL, 0); 148 opt &= ~O_NONBLOCK; 149 fcntl(fd, F_SETFL, opt); 253 150 #endif 254 151 } -
trunk/src/VBox/Devices/Network/slirp/misc.h
r1824 r14964 9 9 #define _MISC_H_ 10 10 11 struct ex_list { 12 int ex_pty; /* Do we want a pty? */ 13 int ex_addr; /* The last byte of the address */ 14 int ex_fport; /* Port to telnet to */ 15 char *ex_exec; /* Command line of what to exec */ 16 struct ex_list *ex_next; 11 struct ex_list 12 { 13 int ex_pty; /* Do we want a pty? */ 14 int ex_addr; /* The last byte of the address */ 15 int ex_fport; /* Port to telnet to */ 16 char *ex_exec; /* Command line of what to exec */ 17 struct ex_list *ex_next; 17 18 }; 18 19 19 20 extern struct ex_list *exec_list; 20 21 21 #ifndef HAVE_STRDUP 22 char *strdup _P((const char *)); 23 #endif 24 25 void do_wait _P((int)); 26 27 #define EMU_NONE 0x0 22 #define EMU_NONE 0x0 28 23 29 24 /* TCP emulations */ 30 #define EMU_CTL 0x131 #define EMU_FTP 0x232 #define EMU_KSH 0x333 #define EMU_IRC 0x425 #define EMU_CTL 0x1 26 #define EMU_FTP 0x2 27 #define EMU_KSH 0x3 28 #define EMU_IRC 0x4 34 29 #define EMU_REALAUDIO 0x5 35 #define EMU_RLOGIN 0x636 #define EMU_IDENT 0x737 #define EMU_RSH 0x830 #define EMU_RLOGIN 0x6 31 #define EMU_IDENT 0x7 32 #define EMU_RSH 0x8 38 33 39 34 #define EMU_NOCONNECT 0x10 /* Don't connect */ 40 35 41 36 /* UDP emulations */ 42 #define EMU_TALK 43 #define EMU_NTALK 44 #define EMU_CUSEEME 37 #define EMU_TALK 0x1 38 #define EMU_NTALK 0x2 39 #define EMU_CUSEEME 0x3 45 40 46 struct tos_t { 47 u_int16_t lport; 48 u_int16_t fport; 49 u_int8_t tos; 50 u_int8_t emu; 41 struct tos_t 42 { 43 u_int16_t lport; 44 u_int16_t fport; 45 u_int8_t tos; 46 u_int8_t emu; 51 47 }; 52 48 53 struct emu_t { 54 u_int16_t lport; 55 u_int16_t fport; 56 u_int8_t tos; 57 u_int8_t emu; 58 struct emu_t *next; 49 struct emu_t 50 { 51 u_int16_t lport; 52 u_int16_t fport; 53 u_int8_t tos; 54 u_int8_t emu; 55 struct emu_t *next; 59 56 }; 60 57 … … 75 72 void relay _P((int)); 76 73 void add_emu _P((char *)); 77 void u_sleep _P((int));78 74 void fd_nonblock _P((int)); 79 75 void fd_block _P((int)); 80 int rsh_exec _P((struct socket *, struct socket *, char *, char *, char *));81 76 82 77 #endif -
trunk/src/VBox/Devices/Network/slirp/sbuf.c
r14470 r14964 17 17 18 18 void 19 sbfree(sb) 20 struct sbuf *sb; 21 { 22 free(sb->sb_data); 23 } 24 25 void 26 sbdrop(sb, num) 27 struct sbuf *sb; 28 int num; 29 { 30 /* 31 * We can only drop how much we have 32 * This should never succeed 33 */ 34 if(num > sb->sb_cc) 35 num = sb->sb_cc; 36 sb->sb_cc -= num; 37 sb->sb_rptr += num; 38 if(sb->sb_rptr >= sb->sb_data + sb->sb_datalen) 39 sb->sb_rptr -= sb->sb_datalen; 40 41 } 42 43 void 44 sbreserve(sb, size) 45 struct sbuf *sb; 46 int size; 47 { 48 if (sb->sb_data) { 49 /* Already alloced, realloc if necessary */ 50 if (sb->sb_datalen != size) { 51 sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size); 52 sb->sb_cc = 0; 53 if (sb->sb_wptr) 54 sb->sb_datalen = size; 55 else 56 sb->sb_datalen = 0; 57 } 58 } else { 59 sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size); 60 sb->sb_cc = 0; 61 if (sb->sb_wptr) 62 sb->sb_datalen = size; 63 else 64 sb->sb_datalen = 0; 19 sbfree(struct sbuf *sb) 20 { 21 free(sb->sb_data); 22 } 23 24 void 25 sbdrop(struct sbuf *sb, int num) 26 { 27 /* 28 * We can only drop how much we have 29 * This should never succeed 30 */ 31 if (num > sb->sb_cc) 32 num = sb->sb_cc; 33 sb->sb_cc -= num; 34 sb->sb_rptr += num; 35 if (sb->sb_rptr >= sb->sb_data + sb->sb_datalen) 36 sb->sb_rptr -= sb->sb_datalen; 37 38 } 39 40 void 41 sbreserve(struct sbuf *sb, int size) 42 { 43 if (sb->sb_data) 44 { 45 /* Already alloced, realloc if necessary */ 46 if (sb->sb_datalen != size) 47 { 48 sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)realloc(sb->sb_data, size); 49 sb->sb_cc = 0; 50 if (sb->sb_wptr) 51 sb->sb_datalen = size; 52 else 53 sb->sb_datalen = 0; 65 54 } 55 } 56 else 57 { 58 sb->sb_wptr = sb->sb_rptr = sb->sb_data = (char *)malloc(size); 59 sb->sb_cc = 0; 60 if (sb->sb_wptr) 61 sb->sb_datalen = size; 62 else 63 sb->sb_datalen = 0; 64 } 66 65 } 67 66 … … 75 74 sbappend(PNATState pData, struct socket *so, struct mbuf *m) 76 75 { 77 int ret = 0; 78 79 DEBUG_CALL("sbappend"); 80 DEBUG_ARG("so = %lx", (long)so); 81 DEBUG_ARG("m = %lx", (long)m); 82 DEBUG_ARG("m->m_len = %d", m->m_len); 83 84 /* Shouldn't happen, but... e.g. foreign host closes connection */ 85 if (m->m_len <= 0) { 86 m_free(pData, m); 87 return; 88 } 89 76 int ret = 0; 77 78 DEBUG_CALL("sbappend"); 79 DEBUG_ARG("so = %lx", (long)so); 80 DEBUG_ARG("m = %lx", (long)m); 81 DEBUG_ARG("m->m_len = %d", m->m_len); 82 83 /* Shouldn't happen, but... e.g. foreign host closes connection */ 84 if (m->m_len <= 0) 85 { 86 m_free(pData, m); 87 return; 88 } 89 90 /* 91 * If there is urgent data, call sosendoob 92 * if not all was sent, sowrite will take care of the rest 93 * (The rest of this function is just an optimisation) 94 */ 95 if (so->so_urgc) 96 { 97 sbappendsb(&so->so_rcv, m); 98 m_free(pData, m); 99 sosendoob(so); 100 return; 101 } 102 103 /* 104 * We only write if there's nothing in the buffer, 105 * ottherwise it'll arrive out of order, and hence corrupt 106 */ 107 if (!so->so_rcv.sb_cc) 108 ret = send(so->s, m->m_data, m->m_len, 0); 109 110 if (ret <= 0) 111 { 90 112 /* 91 * If there is urgent data, call sosendoob 92 * if not all was sent, sowrite will take care of the rest 93 * (The rest of this function is just an optimisation) 113 * Nothing was written 114 * It's possible that the socket has closed, but 115 * we don't need to check because if it has closed, 116 * it will be detected in the normal way by soread() 94 117 */ 95 if (so->so_urgc) { 96 sbappendsb(&so->so_rcv, m); 97 m_free(pData, m); 98 sosendoob(so); 99 return; 100 } 101 118 sbappendsb(&so->so_rcv, m); 119 } 120 else if (ret != m->m_len) 121 { 102 122 /* 103 * We only write if there's nothing in the buffer,104 * ottherwise it'll arrive out of order, and hence corrupt123 * Something was written, but not everything.. 124 * sbappendsb the rest 105 125 */ 106 if (!so->so_rcv.sb_cc) 107 ret = send(so->s, m->m_data, m->m_len, 0); 108 109 if (ret <= 0) { 110 /* 111 * Nothing was written 112 * It's possible that the socket has closed, but 113 * we don't need to check because if it has closed, 114 * it will be detected in the normal way by soread() 115 */ 116 sbappendsb(&so->so_rcv, m); 117 } else if (ret != m->m_len) { 118 /* 119 * Something was written, but not everything.. 120 * sbappendsb the rest 121 */ 122 m->m_len -= ret; 123 m->m_data += ret; 124 sbappendsb(&so->so_rcv, m); 125 } /* else */ 126 /* Whatever happened, we free the mbuf */ 127 m_free(pData, m); 126 m->m_len -= ret; 127 m->m_data += ret; 128 sbappendsb(&so->so_rcv, m); 129 } /* else */ 130 /* Whatever happened, we free the mbuf */ 131 m_free(pData, m); 128 132 } 129 133 … … 133 137 */ 134 138 void 135 sbappendsb(sb, m) 136 struct sbuf *sb; 137 struct mbuf *m; 138 { 139 int len, n, nn; 140 141 len = m->m_len; 142 143 if (sb->sb_wptr < sb->sb_rptr) { 144 n = sb->sb_rptr - sb->sb_wptr; 145 if (n > len) n = len; 146 memcpy(sb->sb_wptr, m->m_data, n); 147 } else { 148 /* Do the right edge first */ 149 n = sb->sb_data + sb->sb_datalen - sb->sb_wptr; 150 if (n > len) n = len; 151 memcpy(sb->sb_wptr, m->m_data, n); 152 len -= n; 153 if (len) { 154 /* Now the left edge */ 155 nn = sb->sb_rptr - sb->sb_data; 156 if (nn > len) nn = len; 157 memcpy(sb->sb_data,m->m_data+n,nn); 158 n += nn; 159 } 139 sbappendsb(struct sbuf *sb, struct mbuf *m) 140 { 141 int len, n, nn; 142 143 len = m->m_len; 144 145 if (sb->sb_wptr < sb->sb_rptr) 146 { 147 n = sb->sb_rptr - sb->sb_wptr; 148 if (n > len) n = len; 149 memcpy(sb->sb_wptr, m->m_data, n); 150 } 151 else 152 { 153 /* Do the right edge first */ 154 n = sb->sb_data + sb->sb_datalen - sb->sb_wptr; 155 if (n > len) n = len; 156 memcpy(sb->sb_wptr, m->m_data, n); 157 len -= n; 158 if (len) 159 { 160 /* Now the left edge */ 161 nn = sb->sb_rptr - sb->sb_data; 162 if (nn > len) 163 nn = len; 164 memcpy(sb->sb_data,m->m_data+n,nn); 165 n += nn; 160 166 } 161 162 sb->sb_cc += n; 163 sb->sb_wptr += n; 164 if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen) 165 sb->sb_wptr -= sb->sb_datalen; 167 } 168 169 sb->sb_cc += n; 170 sb->sb_wptr += n; 171 if (sb->sb_wptr >= sb->sb_data + sb->sb_datalen) 172 sb->sb_wptr -= sb->sb_datalen; 166 173 } 167 174 … … 172 179 */ 173 180 void 174 sbcopy(sb, off, len, to) 175 struct sbuf *sb; 176 int off; 177 int len; 178 char *to; 179 { 180 char *from; 181 182 from = sb->sb_rptr + off; 183 if (from >= sb->sb_data + sb->sb_datalen) 184 from -= sb->sb_datalen; 185 186 if (from < sb->sb_wptr) { 187 if (len > sb->sb_cc) len = sb->sb_cc; 188 memcpy(to,from,len); 189 } else { 190 /* re-use off */ 191 off = (sb->sb_data + sb->sb_datalen) - from; 192 if (off > len) off = len; 193 memcpy(to,from,off); 194 len -= off; 195 if (len) 196 memcpy(to+off,sb->sb_data,len); 197 } 198 } 199 181 sbcopy(struct sbuf *sb, int off, int len, char *to) 182 { 183 char *from; 184 185 from = sb->sb_rptr + off; 186 if (from >= sb->sb_data + sb->sb_datalen) 187 from -= sb->sb_datalen; 188 189 if (from < sb->sb_wptr) 190 { 191 if (len > sb->sb_cc) len = sb->sb_cc; 192 memcpy(to,from,len); 193 } 194 else 195 { 196 /* re-use off */ 197 off = (sb->sb_data + sb->sb_datalen) - from; 198 if (off > len) off = len; 199 memcpy(to,from,off); 200 len -= off; 201 if (len) 202 memcpy(to+off,sb->sb_data,len); 203 } 204 } 205 -
trunk/src/VBox/Devices/Network/slirp/sbuf.h
r14470 r14964 12 12 #define sbspace(sb) ((sb)->sb_datalen - (sb)->sb_cc) 13 13 14 struct sbuf { 15 u_int sb_cc; /* actual chars in buffer */ 16 u_int sb_datalen; /* Length of data */ 17 char *sb_wptr; /* write pointer. points to where the next 18 * bytes should be written in the sbuf */ 19 char *sb_rptr; /* read pointer. points to where the next 20 * byte should be read from the sbuf */ 21 char *sb_data; /* Actual data */ 14 struct sbuf 15 { 16 u_int sb_cc; /* actual chars in buffer */ 17 u_int sb_datalen; /* Length of data */ 18 char *sb_wptr; /* write pointer. points to where the next 19 * bytes should be written in the sbuf */ 20 char *sb_rptr; /* read pointer. points to where the next 21 * byte should be read from the sbuf */ 22 char *sb_data; /* Actual data */ 22 23 }; 23 24 -
trunk/src/VBox/Devices/Network/slirp/slirp.c
r14951 r14964 1055 1055 return 2; 1056 1056 if (do_slowtimo) 1057 return 500; 1057 return 500; /* see PR_SLOWHZ */ 1058 1058 } 1059 1059 return 0; -
trunk/src/VBox/Devices/Network/slirp/slirp.h
r14951 r14964 260 260 void if_start _P((PNATState)); 261 261 262 #ifdef BAD_SPRINTF263 # define vsprintf vsprintf_len264 # define sprintf sprintf_len265 extern int vsprintf_len _P((char *, const char *, va_list));266 extern int sprintf_len _P((char *, const char *, ...));267 #endif268 269 #ifdef DECLARE_SPRINTF270 # ifndef BAD_SPRINTF271 extern int vsprintf _P((char *, const char *, va_list));272 # endif273 extern int vfprintf _P((FILE *, const char *, va_list));274 #endif275 276 #ifndef HAVE_STRERROR277 extern char *strerror _P((int error));278 #endif279 280 262 #ifndef HAVE_INDEX 281 263 char *index _P((const char *, int)); -
trunk/src/VBox/Devices/Network/slirp/slirp_config.h
r14951 r14964 77 77 #endif 78 78 79 /* Define if you have strerror */80 #define HAVE_STRERROR81 82 /* Define if you have strdup() */83 #define HAVE_STRDUP84 85 79 /* Define according to how time.h should be included */ 86 80 #define TIME_WITH_SYS_TIME 0 … … 92 86 /* Define if the machine is big endian */ 93 87 /*#undef WORDS_BIGENDIAN */ 94 95 /* Define if your sprintf returns char * instead of int */96 #undef BAD_SPRINTF97 88 98 89 /* Define if you have readv */ … … 104 95 # define DECLARE_IOVEC 105 96 #endif 106 107 /* Define if a declaration of sprintf/fprintf is needed */108 #undef DECLARE_SPRINTF109 97 110 98 /* Define if you have a POSIX.1 sys/wait.h */ -
trunk/src/VBox/Devices/Network/slirp/socket.c
r14951 r14964 17 17 so_init() 18 18 { 19 /* Nothing yet */20 19 } 21 20 22 21 23 22 struct socket * 24 solookup(head, laddr, lport, faddr, fport) 25 struct socket *head; 26 struct in_addr laddr; 27 u_int lport; 28 struct in_addr faddr; 29 u_int fport; 30 { 31 struct socket *so; 32 33 for (so = head->so_next; so != head; so = so->so_next) { 34 if (so->so_lport == lport && 35 so->so_laddr.s_addr == laddr.s_addr && 36 so->so_faddr.s_addr == faddr.s_addr && 37 so->so_fport == fport) 38 break; 39 } 40 41 if (so == head) 42 return (struct socket *)NULL; 43 return so; 44 23 solookup(struct socket *head, struct in_addr laddr, 24 u_int lport, struct in_addr faddr, u_int fport) 25 { 26 struct socket *so; 27 28 for (so = head->so_next; so != head; so = so->so_next) 29 { 30 if ( so->so_lport == lport 31 && so->so_laddr.s_addr == laddr.s_addr 32 && so->so_faddr.s_addr == faddr.s_addr 33 && so->so_fport == fport) 34 return so; 35 } 36 37 return (struct socket *)NULL; 45 38 } 46 39 … … 53 46 socreate() 54 47 { 55 struct socket *so; 56 57 so = (struct socket *)malloc(sizeof(struct socket)); 58 if(so) { 59 memset(so, 0, sizeof(struct socket)); 60 so->so_state = SS_NOFDREF; 61 so->s = -1; 62 } 63 return(so); 48 struct socket *so; 49 50 so = (struct socket *)malloc(sizeof(struct socket)); 51 if(so) 52 { 53 memset(so, 0, sizeof(struct socket)); 54 so->so_state = SS_NOFDREF; 55 so->s = -1; 56 } 57 return so; 64 58 } 65 59 … … 70 64 sofree(PNATState pData, struct socket *so) 71 65 { 72 if (so->so_emu==EMU_RSH && so->extra) { 73 sofree(pData, so->extra); 74 so->extra=NULL; 75 } 76 if (so == tcp_last_so) 77 tcp_last_so = &tcb; 78 else if (so == udp_last_so) 79 udp_last_so = &udb; 80 81 m_free(pData, so->so_m); 82 83 84 if(so->so_next && so->so_prev) 85 remque(pData, so); /* crashes if so is not in a queue */ 86 87 free(so); 66 if (so == tcp_last_so) 67 tcp_last_so = &tcb; 68 else if (so == udp_last_so) 69 udp_last_so = &udb; 70 71 m_free(pData, so->so_m); 72 73 if(so->so_next && so->so_prev) 74 remque(pData, so); /* crashes if so is not in a queue */ 75 76 free(so); 88 77 } 89 78 … … 96 85 soread(PNATState pData, struct socket *so) 97 86 { 98 int n, nn, lss, total; 99 struct sbuf *sb = &so->so_snd; 100 int len = sb->sb_datalen - sb->sb_cc; 101 struct iovec iov[2]; 102 int mss = so->so_tcpcb->t_maxseg; 103 104 DEBUG_CALL("soread"); 105 DEBUG_ARG("so = %lx", (long )so); 106 87 int n, nn, lss, total; 88 struct sbuf *sb = &so->so_snd; 89 int len = sb->sb_datalen - sb->sb_cc; 90 struct iovec iov[2]; 91 int mss = so->so_tcpcb->t_maxseg; 92 93 DEBUG_CALL("soread"); 94 DEBUG_ARG("so = %lx", (long )so); 95 96 /* 97 * No need to check if there's enough room to read. 98 * soread wouldn't have been called if there weren't 99 */ 100 101 len = sb->sb_datalen - sb->sb_cc; 102 103 iov[0].iov_base = sb->sb_wptr; 104 iov[1].iov_base = 0; 105 iov[1].iov_len = 0; 106 if (sb->sb_wptr < sb->sb_rptr) 107 { 108 iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; 109 /* Should never succeed, but... */ 110 if (iov[0].iov_len > len) 111 iov[0].iov_len = len; 112 if (iov[0].iov_len > mss) 113 iov[0].iov_len -= iov[0].iov_len%mss; 114 n = 1; 115 } 116 else 117 { 118 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr; 119 /* Should never succeed, but... */ 120 if (iov[0].iov_len > len) iov[0].iov_len = len; 121 len -= iov[0].iov_len; 122 if (len) 123 { 124 iov[1].iov_base = sb->sb_data; 125 iov[1].iov_len = sb->sb_rptr - sb->sb_data; 126 if(iov[1].iov_len > len) 127 iov[1].iov_len = len; 128 total = iov[0].iov_len + iov[1].iov_len; 129 if (total > mss) 130 { 131 lss = total % mss; 132 if (iov[1].iov_len > lss) 133 { 134 iov[1].iov_len -= lss; 135 n = 2; 136 } 137 else 138 { 139 lss -= iov[1].iov_len; 140 iov[0].iov_len -= lss; 141 n = 1; 142 } 143 } 144 else 145 n = 2; 146 } 147 else 148 { 149 if (iov[0].iov_len > mss) 150 iov[0].iov_len -= iov[0].iov_len%mss; 151 n = 1; 152 } 153 } 154 155 #ifdef HAVE_READV 156 nn = readv(so->s, (struct iovec *)iov, n); 157 DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); 158 #else 159 nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0); 160 #endif 161 if (nn <= 0) 162 { 163 #if defined(VBOX_WITH_SIMPLIFIED_SLIRP_SYNC) && defined(RT_OS_WINDOWS) 107 164 /* 108 * No need to check if there's enough room to read. 109 * soread wouldn't have been called if there weren't 165 * Special case for WSAEnumNetworkEvents: If we receive 0 bytes that 166 * _could_ mean that the connection is closed. But we will receive an 167 * FD_CLOSE event later if the connection was _really_ closed. With 168 * www.youtube.com I see this very often. Closing the socket too early 169 * would be dangerous. 110 170 */ 111 112 len = sb->sb_datalen - sb->sb_cc; 113 114 iov[0].iov_base = sb->sb_wptr; 115 iov[1].iov_base = 0; 116 iov[1].iov_len = 0; 117 if (sb->sb_wptr < sb->sb_rptr) { 118 iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; 119 /* Should never succeed, but... */ 120 if (iov[0].iov_len > len) 121 iov[0].iov_len = len; 122 if (iov[0].iov_len > mss) 123 iov[0].iov_len -= iov[0].iov_len%mss; 124 n = 1; 125 } else { 126 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr; 127 /* Should never succeed, but... */ 128 if (iov[0].iov_len > len) iov[0].iov_len = len; 129 len -= iov[0].iov_len; 130 if (len) { 131 iov[1].iov_base = sb->sb_data; 132 iov[1].iov_len = sb->sb_rptr - sb->sb_data; 133 if(iov[1].iov_len > len) 134 iov[1].iov_len = len; 135 total = iov[0].iov_len + iov[1].iov_len; 136 if (total > mss) { 137 lss = total%mss; 138 if (iov[1].iov_len > lss) { 139 iov[1].iov_len -= lss; 140 n = 2; 141 } else { 142 lss -= iov[1].iov_len; 143 iov[0].iov_len -= lss; 144 n = 1; 145 } 146 } else 147 n = 2; 148 } else { 149 if (iov[0].iov_len > mss) 150 iov[0].iov_len -= iov[0].iov_len%mss; 151 n = 1; 152 } 153 } 154 155 #ifdef HAVE_READV 156 nn = readv(so->s, (struct iovec *)iov, n); 157 DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); 158 #else 159 nn = recv(so->s, iov[0].iov_base, iov[0].iov_len,0); 160 #endif 161 if (nn <= 0) { 162 #if defined(VBOX_WITH_SIMPLIFIED_SLIRP_SYNC) && defined(RT_OS_WINDOWS) 163 /* 164 * Special case for WSAEnumNetworkEvents: If we receive 0 bytes that 165 * _could_ mean that the connection is closed. But we will receive an 166 * FD_CLOSE event later if the connection was _really_ closed. With 167 * www.youtube.com I see this very often. Closing the socket too early 168 * would be dangerous. 169 */ 170 if (nn == 0) 171 return 0; 172 #endif 173 if (nn < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) 174 return 0; 175 else { 176 /* nn == 0 means peer has performed an orderly shutdown */ 177 DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); 178 sofcantrcvmore(so); 179 tcp_sockclosed(pData, sototcpcb(so)); 180 return -1; 181 } 182 } 171 if (nn == 0) 172 return 0; 173 #endif 174 if (nn < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)) 175 return 0; 176 else 177 { 178 /* nn == 0 means peer has performed an orderly shutdown */ 179 DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", 180 nn, errno,strerror(errno))); 181 sofcantrcvmore(so); 182 tcp_sockclosed(pData, sototcpcb(so)); 183 return -1; 184 } 185 } 183 186 184 187 #ifndef HAVE_READV 185 /* 186 * If there was no error, try and read the second time round 187 * We read again if n = 2 (ie, there's another part of the buffer) 188 * and we read as much as we could in the first read 189 * We don't test for <= 0 this time, because there legitimately 190 * might not be any more data (since the socket is non-blocking), 191 * a close will be detected on next iteration. 192 * A return of -1 wont (shouldn't) happen, since it didn't happen above 193 */ 194 if (n == 2 && nn == iov[0].iov_len) { 195 int ret; 196 ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0); 197 if (ret > 0) 198 nn += ret; 199 } 200 201 DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); 202 #endif 203 204 /* Update fields */ 205 sb->sb_cc += nn; 206 sb->sb_wptr += nn; 207 if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) 208 sb->sb_wptr -= sb->sb_datalen; 209 return nn; 188 /* 189 * If there was no error, try and read the second time round 190 * We read again if n = 2 (ie, there's another part of the buffer) 191 * and we read as much as we could in the first read 192 * We don't test for <= 0 this time, because there legitimately 193 * might not be any more data (since the socket is non-blocking), 194 * a close will be detected on next iteration. 195 * A return of -1 wont (shouldn't) happen, since it didn't happen above 196 */ 197 if (n == 2 && nn == iov[0].iov_len) 198 { 199 int ret; 200 ret = recv(so->s, iov[1].iov_base, iov[1].iov_len,0); 201 if (ret > 0) 202 nn += ret; 203 } 204 205 DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); 206 #endif 207 208 /* Update fields */ 209 sb->sb_cc += nn; 210 sb->sb_wptr += nn; 211 if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) 212 sb->sb_wptr -= sb->sb_datalen; 213 return nn; 210 214 } 211 215 … … 220 224 sorecvoob(PNATState pData, struct socket *so) 221 225 { 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 226 struct tcpcb *tp = sototcpcb(so); 227 228 DEBUG_CALL("sorecvoob"); 229 DEBUG_ARG("so = %lx", (long)so); 230 231 /* 232 * We take a guess at how much urgent data has arrived. 233 * In most situations, when urgent data arrives, the next 234 * read() should get all the urgent data. This guess will 235 * be wrong however if more data arrives just after the 236 * urgent data, or the read() doesn't return all the 237 * urgent data. 238 */ 239 soread(pData, so); 240 tp->snd_up = tp->snd_una + so->so_snd.sb_cc; 241 tp->t_force = 1; 242 tcp_output(pData, tp); 243 tp->t_force = 0; 240 244 } 241 245 … … 245 249 */ 246 250 int 247 sosendoob(so) 248 struct socket *so; 249 { 250 struct sbuf *sb = &so->so_rcv; 251 char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ 252 253 int n, len; 254 255 DEBUG_CALL("sosendoob"); 256 DEBUG_ARG("so = %lx", (long)so); 257 DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); 258 259 if (so->so_urgc > 2048) 260 so->so_urgc = 2048; /* XXXX */ 261 262 if (sb->sb_rptr < sb->sb_wptr) { 263 /* We can send it directly */ 264 n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ 265 so->so_urgc -= n; 266 267 DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); 268 } else { 269 /* 270 * Since there's no sendv or sendtov like writev, 271 * we must copy all data to a linear buffer then 272 * send it all 273 */ 274 len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; 275 if (len > so->so_urgc) len = so->so_urgc; 276 memcpy(buff, sb->sb_rptr, len); 277 so->so_urgc -= len; 278 if (so->so_urgc) { 279 n = sb->sb_wptr - sb->sb_data; 280 if (n > so->so_urgc) n = so->so_urgc; 281 memcpy((buff + len), sb->sb_data, n); 282 so->so_urgc -= n; 283 len += n; 284 } 285 n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ 251 sosendoob(struct socket *so) 252 { 253 struct sbuf *sb = &so->so_rcv; 254 char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ 255 256 int n, len; 257 258 DEBUG_CALL("sosendoob"); 259 DEBUG_ARG("so = %lx", (long)so); 260 DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); 261 262 if (so->so_urgc > sizeof(buff)) 263 so->so_urgc = sizeof(buff); /* XXX */ 264 265 if (sb->sb_rptr < sb->sb_wptr) 266 { 267 /* We can send it directly */ 268 n = send(so->s, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ 269 so->so_urgc -= n; 270 271 DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", 272 n, so->so_urgc)); 273 } 274 else 275 { 276 /* 277 * Since there's no sendv or sendtov like writev, 278 * we must copy all data to a linear buffer then 279 * send it all 280 */ 281 len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; 282 if (len > so->so_urgc) len = so->so_urgc; 283 memcpy(buff, sb->sb_rptr, len); 284 so->so_urgc -= len; 285 if (so->so_urgc) 286 { 287 n = sb->sb_wptr - sb->sb_data; 288 if (n > so->so_urgc) 289 n = so->so_urgc; 290 memcpy(buff + len, sb->sb_data, n); 291 so->so_urgc -= n; 292 len += n; 293 } 294 n = send(so->s, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ 286 295 #ifdef DEBUG 287 if (n != len) 288 DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); 289 #endif 290 DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); 291 } 292 293 sb->sb_cc -= n; 294 sb->sb_rptr += n; 295 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) 296 sb->sb_rptr -= sb->sb_datalen; 297 298 return n; 296 if (n != len) 297 DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); 298 #endif 299 DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", 300 n, so->so_urgc)); 301 } 302 303 sb->sb_cc -= n; 304 sb->sb_rptr += n; 305 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) 306 sb->sb_rptr -= sb->sb_datalen; 307 308 return n; 299 309 } 300 310 … … 306 316 sowrite(PNATState pData, struct socket *so) 307 317 { 308 int n,nn; 309 struct sbuf *sb = &so->so_rcv; 310 int len = sb->sb_cc; 311 struct iovec iov[2]; 312 313 DEBUG_CALL("sowrite"); 314 DEBUG_ARG("so = %lx", (long)so); 315 316 if (so->so_urgc) { 317 sosendoob(so); 318 if (sb->sb_cc == 0) 319 return 0; 320 } 321 322 /* 323 * No need to check if there's something to write, 324 * sowrite wouldn't have been called otherwise 325 */ 326 327 len = sb->sb_cc; 328 329 iov[0].iov_base = sb->sb_rptr; 330 iov[1].iov_base = 0; 331 iov[1].iov_len = 0; 332 if (sb->sb_rptr < sb->sb_wptr) { 333 iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; 334 /* Should never succeed, but... */ 335 if (iov[0].iov_len > len) iov[0].iov_len = len; 336 n = 1; 337 } else { 338 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; 339 if (iov[0].iov_len > len) iov[0].iov_len = len; 340 len -= iov[0].iov_len; 341 if (len) { 342 iov[1].iov_base = sb->sb_data; 343 iov[1].iov_len = sb->sb_wptr - sb->sb_data; 344 if (iov[1].iov_len > len) iov[1].iov_len = len; 345 n = 2; 346 } else 347 n = 1; 348 } 349 /* Check if there's urgent data to send, and if so, send it */ 350 318 int n,nn; 319 struct sbuf *sb = &so->so_rcv; 320 int len = sb->sb_cc; 321 struct iovec iov[2]; 322 323 DEBUG_CALL("sowrite"); 324 DEBUG_ARG("so = %lx", (long)so); 325 326 if (so->so_urgc) 327 { 328 sosendoob(so); 329 if (sb->sb_cc == 0) 330 return 0; 331 } 332 333 /* 334 * No need to check if there's something to write, 335 * sowrite wouldn't have been called otherwise 336 */ 337 338 len = sb->sb_cc; 339 340 iov[0].iov_base = sb->sb_rptr; 341 iov[1].iov_base = 0; 342 iov[1].iov_len = 0; 343 if (sb->sb_rptr < sb->sb_wptr) 344 { 345 iov[0].iov_len = sb->sb_wptr - sb->sb_rptr; 346 /* Should never succeed, but... */ 347 if (iov[0].iov_len > len) iov[0].iov_len = len; 348 n = 1; 349 } 350 else 351 { 352 iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; 353 if (iov[0].iov_len > len) iov[0].iov_len = len; 354 len -= iov[0].iov_len; 355 if (len) 356 { 357 iov[1].iov_base = sb->sb_data; 358 iov[1].iov_len = sb->sb_wptr - sb->sb_data; 359 if (iov[1].iov_len > len) 360 iov[1].iov_len = len; 361 n = 2; 362 } 363 else 364 n = 1; 365 } 366 /* Check if there's urgent data to send, and if so, send it */ 351 367 #ifdef HAVE_READV 352 nn = writev(so->s, (const struct iovec *)iov, n); 353 354 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 368 nn = writev(so->s, (const struct iovec *)iov, n); 369 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 355 370 #else 356 nn = send(so->s, iov[0].iov_base, iov[0].iov_len,0); 357 #endif 358 /* This should never happen, but people tell me it does *shrug* */ 359 if (nn < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) 360 return 0; 361 362 if (nn < 0 || (nn == 0 && iov[0].iov_len > 0)) { 363 DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", 364 so->so_state, errno)); 365 sofcantsendmore(so); 366 tcp_sockclosed(pData, sototcpcb(so)); 367 return -1; 368 } 371 nn = send(so->s, iov[0].iov_base, iov[0].iov_len, 0); 372 #endif 373 /* This should never happen, but people tell me it does *shrug* */ 374 if (nn < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) 375 return 0; 376 377 if (nn < 0 || (nn == 0 && iov[0].iov_len > 0)) 378 { 379 DEBUG_MISC((dfd, " --- sowrite disconnected, so->so_state = %x, errno = %d\n", 380 so->so_state, errno)); 381 sofcantsendmore(so); 382 tcp_sockclosed(pData, sototcpcb(so)); 383 return -1; 384 } 369 385 370 386 #ifndef HAVE_READV 371 if (n == 2 && nn == iov[0].iov_len) { 372 int ret; 373 ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0); 374 if (ret > 0) 375 nn += ret; 376 } 377 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 378 #endif 379 380 /* Update sbuf */ 381 sb->sb_cc -= nn; 382 sb->sb_rptr += nn; 383 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) 384 sb->sb_rptr -= sb->sb_datalen; 385 386 /* 387 * If in DRAIN mode, and there's no more data, set 388 * it CANTSENDMORE 389 */ 390 if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) 391 sofcantsendmore(so); 392 393 return nn; 387 if (n == 2 && nn == iov[0].iov_len) 388 { 389 int ret; 390 ret = send(so->s, iov[1].iov_base, iov[1].iov_len,0); 391 if (ret > 0) 392 nn += ret; 393 } 394 DEBUG_MISC((dfd, " ... wrote nn = %d bytes\n", nn)); 395 #endif 396 397 /* Update sbuf */ 398 sb->sb_cc -= nn; 399 sb->sb_rptr += nn; 400 if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) 401 sb->sb_rptr -= sb->sb_datalen; 402 403 /* 404 * If in DRAIN mode, and there's no more data, set 405 * it CANTSENDMORE 406 */ 407 if ((so->so_state & SS_FWDRAIN) && sb->sb_cc == 0) 408 sofcantsendmore(so); 409 410 return nn; 394 411 } 395 412 … … 400 417 sorecvfrom(PNATState pData, struct socket *so) 401 418 { 402 struct sockaddr_in addr; 403 socklen_t addrlen = sizeof(struct sockaddr_in); 404 405 DEBUG_CALL("sorecvfrom"); 406 DEBUG_ARG("so = %lx", (long)so); 407 408 if (so->so_type == IPPROTO_ICMP) { /* This is a "ping" reply */ 409 char buff[256]; 410 int len; 411 412 len = recvfrom(so->s, buff, 256, 0, 413 (struct sockaddr *)&addr, &addrlen); 414 /* XXX Check if reply is "correct"? */ 415 416 if(len == -1 || len == 0) { 417 u_char code=ICMP_UNREACH_PORT; 418 419 if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; 420 else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; 419 struct sockaddr_in addr; 420 socklen_t addrlen = sizeof(struct sockaddr_in); 421 422 DEBUG_CALL("sorecvfrom"); 423 DEBUG_ARG("so = %lx", (long)so); 424 425 if (so->so_type == IPPROTO_ICMP) 426 { 427 /* This is a "ping" reply */ 428 char buff[256]; 429 int len; 430 431 len = recvfrom(so->s, buff, sizeof(buff), 0, 432 (struct sockaddr *)&addr, &addrlen); 433 /* XXX Check if reply is "correct"? */ 434 435 if(len == -1 || len == 0) 436 { 437 u_char code = ICMP_UNREACH_PORT; 438 439 if (errno == EHOSTUNREACH) 440 code=ICMP_UNREACH_HOST; 441 else if(errno == ENETUNREACH) 442 code=ICMP_UNREACH_NET; 421 443 422 444 DEBUG_MISC((dfd," udp icmp rx errno = %d-%s\n", 423 445 errno,strerror(errno))); 424 446 icmp_error(pData, so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); 425 } else { 447 } 448 else 449 { 426 450 #ifdef VBOX_WITH_SLIRP_ICMP 427 451 struct ip *ip; … … 439 463 icmp_reflect(pData, so->so_m); 440 464 so->so_m = 0; /* Don't m_free() it again! */ 441 } 442 /* No need for this socket anymore, udp_detach it */ 443 udp_detach(pData, so); 444 } else { /* A "normal" UDP packet */ 445 struct mbuf *m; 446 int len, n; 447 448 if (!(m = m_get(pData))) return; 449 m->m_data += if_maxlinkhdr; 450 451 /* 452 * XXX Shouldn't FIONREAD packets destined for port 53, 453 * but I don't know the max packet size for DNS lookups 454 */ 455 len = M_FREEROOM(m); 456 /* if (so->so_fport != htons(53)) { */ 457 ioctlsocket(so->s, FIONREAD, &n); 458 459 if (n > len) { 460 n = (m->m_data - m->m_dat) + m->m_len + n + 1; 461 m_inc(m, n); 462 len = M_FREEROOM(m); 463 } 464 /* } */ 465 466 m->m_len = recvfrom(so->s, m->m_data, len, 0, 467 (struct sockaddr *)&addr, &addrlen); 468 DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n", 469 m->m_len, errno,strerror(errno))); 470 if(m->m_len<0) { 465 } 466 /* No need for this socket anymore, udp_detach it */ 467 udp_detach(pData, so); 468 } 469 else 470 { 471 /* A "normal" UDP packet */ 472 struct mbuf *m; 473 int len, n; 474 475 if (!(m = m_get(pData))) 476 return; 477 m->m_data += if_maxlinkhdr; 478 479 /* 480 * XXX Shouldn't FIONREAD packets destined for port 53, 481 * but I don't know the max packet size for DNS lookups 482 */ 483 len = M_FREEROOM(m); 484 /* if (so->so_fport != htons(53)) */ 485 { 486 ioctlsocket(so->s, FIONREAD, &n); 487 488 if (n > len) 489 { 490 n = (m->m_data - m->m_dat) + m->m_len + n + 1; 491 m_inc(m, n); 492 len = M_FREEROOM(m); 493 } 494 } 495 496 m->m_len = recvfrom(so->s, m->m_data, len, 0, 497 (struct sockaddr *)&addr, &addrlen); 498 DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n", 499 m->m_len, errno,strerror(errno))); 500 if(m->m_len < 0) 501 { 471 502 u_char code=ICMP_UNREACH_PORT; 472 503 473 if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; 474 else if(errno == ENETUNREACH) code=ICMP_UNREACH_NET; 504 if (errno == EHOSTUNREACH) 505 code=ICMP_UNREACH_HOST; 506 else if(errno == ENETUNREACH) 507 code=ICMP_UNREACH_NET; 475 508 476 509 DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code)); 477 510 icmp_error(pData, so->so_m, ICMP_UNREACH,code, 0,strerror(errno)); 478 511 m_free(pData, m); 479 } else { 480 /* 481 * Hack: domain name lookup will be used the most for UDP, 482 * and since they'll only be used once there's no need 483 * for the 4 minute (or whatever) timeout... So we time them 484 * out much quicker (10 seconds for now...) 485 */ 486 if (so->so_expire) { 487 if (so->so_fport == htons(53)) 488 so->so_expire = curtime + SO_EXPIREFAST; 489 else 490 so->so_expire = curtime + SO_EXPIRE; 512 } 513 else 514 { 515 /* 516 * Hack: domain name lookup will be used the most for UDP, 517 * and since they'll only be used once there's no need 518 * for the 4 minute (or whatever) timeout... So we time them 519 * out much quicker (10 seconds for now...) 520 */ 521 if (so->so_expire) 522 { 523 if (so->so_fport == htons(53)) 524 so->so_expire = curtime + SO_EXPIREFAST; 525 else 526 so->so_expire = curtime + SO_EXPIRE; 491 527 } 492 528 493 /* if (m->m_len == len) { 494 * m_inc(m, MINCSIZE); 495 * m->m_len = 0; 496 * } 497 */ 529 #if 0 530 if (m->m_len == len) 531 { 532 m_inc(m, MINCSIZE); 533 m->m_len = 0; 534 } 535 #endif 498 536 499 537 /* … … 502 540 */ 503 541 udp_output(pData, so, m, &addr); 504 505 542 } /* rx error */ 543 } /* if ping packet */ 506 544 } 507 545 … … 512 550 sosendto(PNATState pData, struct socket *so, struct mbuf *m) 513 551 { 514 515 552 int ret; 553 struct sockaddr_in addr; 516 554 #if 0 517 struct sockaddr_in host_addr; 518 #endif 519 520 DEBUG_CALL("sosendto"); 521 DEBUG_ARG("so = %lx", (long)so); 522 DEBUG_ARG("m = %lx", (long)m); 523 524 addr.sin_family = AF_INET; 525 if ((so->so_faddr.s_addr & htonl(pData->netmask)) == special_addr.s_addr) { 526 /* It's an alias */ 527 uint32_t last_byte = ntohl(so->so_faddr.s_addr) & ~pData->netmask; 528 switch(last_byte) { 555 struct sockaddr_in host_addr; 556 #endif 557 558 DEBUG_CALL("sosendto"); 559 DEBUG_ARG("so = %lx", (long)so); 560 DEBUG_ARG("m = %lx", (long)m); 561 562 addr.sin_family = AF_INET; 563 if ((so->so_faddr.s_addr & htonl(pData->netmask)) == special_addr.s_addr) 564 { 565 /* It's an alias */ 566 uint32_t last_byte = ntohl(so->so_faddr.s_addr) & ~pData->netmask; 567 switch(last_byte) 568 { 529 569 #if 0 530 /* handle this case at 'default:' */531 case CTL_BROADCAST:532 addr.sin_addr.s_addr = INADDR_BROADCAST;533 # if 0 534 /* Send the packet to host to fully emulate broadcast */535 /** @todo r=klaus: on Linux host this causes the host to receive536 * the packet twice for some reason. And I cannot find any place537 * in the man pages which states that sending a broadcast does not538 * reach the host itself. */539 host_addr.sin_family = AF_INET;540 host_addr.sin_port = so->so_fport;541 host_addr.sin_addr = our_addr;542 sendto(so->s, m->m_data, m->m_len, 0,543 (struct sockaddr *)&host_addr, sizeof (struct sockaddr));544 # 545 break;546 #endif 547 case CTL_DNS:548 if (!get_dns_addr(pData, &dns_addr))549 addr.sin_addr = dns_addr;550 else551 addr.sin_addr = loopback_addr;552 break;553 case CTL_ALIAS:554 default:555 if (last_byte == ~pData->netmask)556 addr.sin_addr.s_addr = INADDR_BROADCAST;557 else558 addr.sin_addr = loopback_addr;559 break;560 }561 } else562 addr.sin_addr = so->so_faddr;563 addr.sin_port = so->so_fport; 564 565 DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n",ntohs(addr.sin_port), inet_ntoa(addr.sin_addr)));566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 570 /* handle this case at 'default:' */ 571 case CTL_BROADCAST: 572 addr.sin_addr.s_addr = INADDR_BROADCAST; 573 /* Send the packet to host to fully emulate broadcast */ 574 /** @todo r=klaus: on Linux host this causes the host to receive 575 * the packet twice for some reason. And I cannot find any place 576 * in the man pages which states that sending a broadcast does not 577 * reach the host itself. */ 578 host_addr.sin_family = AF_INET; 579 host_addr.sin_port = so->so_fport; 580 host_addr.sin_addr = our_addr; 581 sendto(so->s, m->m_data, m->m_len, 0, 582 (struct sockaddr *)&host_addr, sizeof (struct sockaddr)); 583 break; 584 #endif 585 case CTL_DNS: 586 if (!get_dns_addr(pData, &dns_addr)) 587 addr.sin_addr = dns_addr; 588 else 589 addr.sin_addr = loopback_addr; 590 break; 591 case CTL_ALIAS: 592 default: 593 if (last_byte == ~pData->netmask) 594 addr.sin_addr.s_addr = INADDR_BROADCAST; 595 else 596 addr.sin_addr = loopback_addr; 597 break; 598 } 599 } 600 else 601 addr.sin_addr = so->so_faddr; 602 addr.sin_port = so->so_fport; 603 604 DEBUG_MISC((dfd, " sendto()ing, addr.sin_port=%d, addr.sin_addr.s_addr=%.16s\n", 605 ntohs(addr.sin_port), inet_ntoa(addr.sin_addr))); 606 607 /* Don't care what port we get */ 608 ret = sendto(so->s, m->m_data, m->m_len, 0, 609 (struct sockaddr *)&addr, sizeof (struct sockaddr)); 610 if (ret < 0) 611 return -1; 612 613 /* 614 * Kill the socket if there's no reply in 4 minutes, 615 * but only if it's an expirable socket 616 */ 617 if (so->so_expire) 618 so->so_expire = curtime + SO_EXPIRE; 619 so->so_state = SS_ISFCONNECTED; /* So that it gets select()ed */ 620 return 0; 581 621 } 582 622 … … 587 627 solisten(PNATState pData, u_int port, u_int32_t laddr, u_int lport, int flags) 588 628 { 589 struct sockaddr_in addr; 590 struct socket *so; 591 socklen_t addrlen = sizeof(addr); 592 int s, opt = 1; 593 594 DEBUG_CALL("solisten"); 595 DEBUG_ARG("port = %d", port); 596 DEBUG_ARG("laddr = %x", laddr); 597 DEBUG_ARG("lport = %d", lport); 598 DEBUG_ARG("flags = %x", flags); 599 600 if ((so = socreate()) == NULL) { 601 /* free(so); Not sofree() ??? free(NULL) == NOP */ 602 return NULL; 603 } 604 605 /* Don't tcp_attach... we don't need so_snd nor so_rcv */ 606 if ((so->so_tcpcb = tcp_newtcpcb(pData, so)) == NULL) { 607 free(so); 608 return NULL; 609 } 610 insque(pData, so,&tcb); 611 612 /* 613 * SS_FACCEPTONCE sockets must time out. 614 */ 615 if (flags & SS_FACCEPTONCE) 616 so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2; 617 618 so->so_state = (SS_FACCEPTCONN|flags); 619 so->so_lport = lport; /* Kept in network format */ 620 so->so_laddr.s_addr = laddr; /* Ditto */ 621 622 addr.sin_family = AF_INET; 623 addr.sin_addr.s_addr = INADDR_ANY; 624 addr.sin_port = port; 625 626 if (((s = socket(AF_INET,SOCK_STREAM,0)) < 0) || 627 (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) || 628 (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) || 629 (listen(s,1) < 0)) { 629 struct sockaddr_in addr; 630 struct socket *so; 631 socklen_t addrlen = sizeof(addr); 632 int s, opt = 1; 633 634 DEBUG_CALL("solisten"); 635 DEBUG_ARG("port = %d", port); 636 DEBUG_ARG("laddr = %x", laddr); 637 DEBUG_ARG("lport = %d", lport); 638 DEBUG_ARG("flags = %x", flags); 639 640 if ((so = socreate()) == NULL) 641 { 642 /* free(so); Not sofree() ??? free(NULL) == NOP */ 643 return NULL; 644 } 645 646 /* Don't tcp_attach... we don't need so_snd nor so_rcv */ 647 if ((so->so_tcpcb = tcp_newtcpcb(pData, so)) == NULL) 648 { 649 free(so); 650 return NULL; 651 } 652 insque(pData, so,&tcb); 653 654 /* 655 * SS_FACCEPTONCE sockets must time out. 656 */ 657 if (flags & SS_FACCEPTONCE) 658 so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2; 659 660 so->so_state = (SS_FACCEPTCONN|flags); 661 so->so_lport = lport; /* Kept in network format */ 662 so->so_laddr.s_addr = laddr; /* Ditto */ 663 664 addr.sin_family = AF_INET; 665 addr.sin_addr.s_addr = INADDR_ANY; 666 addr.sin_port = port; 667 668 if ( ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) 669 || (setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int)) < 0) 670 || (bind(s,(struct sockaddr *)&addr, sizeof(addr)) < 0) 671 || (listen(s,1) < 0)) 672 { 630 673 #ifdef RT_OS_WINDOWS 631 632 633 634 635 674 int tmperrno = WSAGetLastError(); /* Don't clobber the real reason we failed */ 675 closesocket(s); 676 sofree(pData, so); 677 /* Restore the real errno */ 678 WSASetLastError(tmperrno); 636 679 #else 637 638 639 640 641 642 #endif 643 644 645 646 647 648 649 650 651 652 653 654 655 680 int tmperrno = errno; /* Don't clobber the real reason we failed */ 681 close(s); 682 sofree(pData, so); 683 /* Restore the real errno */ 684 errno = tmperrno; 685 #endif 686 return NULL; 687 } 688 setsockopt(s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int)); 689 690 getsockname(s,(struct sockaddr *)&addr,&addrlen); 691 so->so_fport = addr.sin_port; 692 if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr) 693 so->so_faddr = alias_addr; 694 else 695 so->so_faddr = addr.sin_addr; 696 697 so->s = s; 698 return so; 656 699 } 657 700 … … 662 705 */ 663 706 void 664 sorwakeup(so) 665 struct socket *so; 666 { 667 /* sowrite(so); */ 668 /* FD_CLR(so->s,&writefds); */ 707 sorwakeup(struct socket *so) 708 { 709 #if 0 710 sowrite(so); 711 FD_CLR(so->s,&writefds); 712 #endif 669 713 } 670 714 … … 675 719 */ 676 720 void 677 sowwakeup(so) 678 struct socket *so; 679 { 680 /* Nothing, yet */ 721 sowwakeup(struct socket *so) 722 { 681 723 } 682 724 … … 688 730 */ 689 731 void 690 soisfconnecting(so) 691 register struct socket *so; 692 { 693 so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE| 694 SS_FCANTSENDMORE|SS_FWDRAIN); 695 so->so_state |= SS_ISFCONNECTING; /* Clobber other states */ 696 } 697 698 void 699 soisfconnected(so) 700 register struct socket *so; 701 { 702 so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF); 703 so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ 704 } 705 706 void 707 sofcantrcvmore(so) 708 struct socket *so; 709 { 710 if ((so->so_state & SS_NOFDREF) == 0) { 711 shutdown(so->s,0); 712 } 713 so->so_state &= ~(SS_ISFCONNECTING); 714 if (so->so_state & SS_FCANTSENDMORE) 715 so->so_state = SS_NOFDREF; /* Don't select it */ /* XXX close() here as well? */ 716 else 717 so->so_state |= SS_FCANTRCVMORE; 718 } 719 720 void 721 sofcantsendmore(so) 722 struct socket *so; 723 { 724 if ((so->so_state & SS_NOFDREF) == 0) { 725 shutdown(so->s,1); /* send FIN to fhost */ 726 } 727 so->so_state &= ~(SS_ISFCONNECTING); 728 if (so->so_state & SS_FCANTRCVMORE) 729 so->so_state = SS_NOFDREF; /* as above */ 730 else 731 so->so_state |= SS_FCANTSENDMORE; 732 } 733 734 void 735 soisfdisconnected(so) 736 struct socket *so; 737 { 738 /* so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); */ 739 /* close(so->s); */ 740 /* so->so_state = SS_ISFDISCONNECTED; */ 741 /* 742 * XXX Do nothing ... ? 743 */ 732 soisfconnecting(struct socket *so) 733 { 734 so->so_state &= ~(SS_NOFDREF|SS_ISFCONNECTED|SS_FCANTRCVMORE| 735 SS_FCANTSENDMORE|SS_FWDRAIN); 736 so->so_state |= SS_ISFCONNECTING; /* Clobber other states */ 737 } 738 739 void 740 soisfconnected(struct socket *so) 741 { 742 so->so_state &= ~(SS_ISFCONNECTING|SS_FWDRAIN|SS_NOFDREF); 743 so->so_state |= SS_ISFCONNECTED; /* Clobber other states */ 744 } 745 746 void 747 sofcantrcvmore(struct socket *so) 748 { 749 if ((so->so_state & SS_NOFDREF) == 0) 750 { 751 shutdown(so->s,0); 752 } 753 so->so_state &= ~(SS_ISFCONNECTING); 754 if (so->so_state & SS_FCANTSENDMORE) 755 so->so_state = SS_NOFDREF; /* Don't select it */ 756 /* XXX close() here as well? */ 757 else 758 so->so_state |= SS_FCANTRCVMORE; 759 } 760 761 void 762 sofcantsendmore(struct socket *so) 763 { 764 if ((so->so_state & SS_NOFDREF) == 0) 765 shutdown(so->s, 1); /* send FIN to fhost */ 766 767 so->so_state &= ~(SS_ISFCONNECTING); 768 if (so->so_state & SS_FCANTRCVMORE) 769 so->so_state = SS_NOFDREF; /* as above */ 770 else 771 so->so_state |= SS_FCANTSENDMORE; 772 } 773 774 void 775 soisfdisconnected(struct socket *so) 776 { 777 #if 0 778 so->so_state &= ~(SS_ISFCONNECTING|SS_ISFCONNECTED); 779 close(so->s); 780 so->so_state = SS_ISFDISCONNECTED; 781 /* 782 * XXX Do nothing ... ? 783 */ 784 #endif 744 785 } 745 786 … … 749 790 */ 750 791 void 751 sofwdrain(so) 752 struct socket *so; 753 { 754 if (so->so_rcv.sb_cc) 755 so->so_state |= SS_FWDRAIN; 756 else 757 sofcantsendmore(so); 758 } 759 792 sofwdrain(struct socket *so) 793 { 794 if (so->so_rcv.sb_cc) 795 so->so_state |= SS_FWDRAIN; 796 else 797 sofcantsendmore(so); 798 } -
trunk/src/VBox/Devices/Network/slirp/socket.h
r14470 r14964 18 18 */ 19 19 20 struct socket { 21 struct socket *so_next,*so_prev; /* For a linked list of sockets */ 20 struct socket 21 { 22 struct socket *so_next; 23 struct socket *so_prev; /* For a linked list of sockets */ 22 24 23 int s;/* The actual socket */25 int s; /* The actual socket */ 24 26 25 26 struct mbuf *so_m;/* Pointer to the original SYN packet,27 28 29 struct tcpiphdr *so_ti;/* Pointer to the original ti within30 31 intso_urgc;32 struct in_addr so_faddr;/* foreign host table entry */33 struct in_addr so_laddr;/* local host table entry */34 u_int16_t so_fport;/* foreign port */35 u_int16_t so_lport;/* local port */27 /* XXX union these with not-yet-used sbuf params */ 28 struct mbuf *so_m; /* Pointer to the original SYN packet, 29 * for non-blocking connect()'s, and 30 * PING reply's */ 31 struct tcpiphdr *so_ti; /* Pointer to the original ti within 32 * so_mconn, for non-blocking connections */ 33 int so_urgc; 34 struct in_addr so_faddr; /* foreign host table entry */ 35 struct in_addr so_laddr; /* local host table entry */ 36 u_int16_t so_fport; /* foreign port */ 37 u_int16_t so_lport; /* local port */ 36 38 37 u_int8_t so_iptos;/* Type of service */38 u_int8_t so_emu;/* Is the socket emulated? */39 u_int8_t so_iptos; /* Type of service */ 40 u_int8_t so_emu; /* Is the socket emulated? */ 39 41 40 u_char so_type;/* Type of socket, UDP or TCP */41 int so_state;/* internal state flags SS_*, below */42 u_char so_type; /* Type of socket, UDP or TCP */ 43 int so_state; /* internal state flags SS_*, below */ 42 44 43 struct tcpcb *so_tcpcb;/* pointer to TCP protocol control block */44 u_int so_expire;/* When the socket will expire */45 struct tcpcb *so_tcpcb; /* pointer to TCP protocol control block */ 46 u_int so_expire; /* When the socket will expire */ 45 47 46 int so_queued;/* Number of packets queued from this socket */47 int so_nqueued;/* Number of packets queued in a row48 * Used to determine when to "downgrade" a session49 48 int so_queued; /* Number of packets queued from this socket */ 49 int so_nqueued; /* Number of packets queued in a row 50 * Used to determine when to "downgrade" a session 51 * from fastq to batchq */ 50 52 51 struct sbuf so_rcv; /* Receive buffer */ 52 struct sbuf so_snd; /* Send buffer */ 53 void * extra; /* Extra pointer */ 53 struct sbuf so_rcv; /* Receive buffer */ 54 struct sbuf so_snd; /* Send buffer */ 54 55 }; 55 56 … … 74 75 extern struct socket tcb; 75 76 76 77 77 #if defined(DECLARE_IOVEC) && !defined(HAVE_READV) 78 struct iovec { 79 char *iov_base; 80 size_t iov_len; 78 struct iovec 79 { 80 char *iov_base; 81 size_t iov_len; 81 82 }; 82 83 #endif -
trunk/src/VBox/Devices/Network/slirp/tcp_timer.c
r14470 r14964 44 44 tcp_fasttimo(PNATState pData) 45 45 { 46 47 48 49 50 51 52 46 register struct socket *so; 47 register struct tcpcb *tp; 48 49 DEBUG_CALL("tcp_fasttimo"); 50 51 so = tcb.so_next; 52 if (so) 53 53 for (; so != &tcb; so = so->so_next) 54 if ((tp = (struct tcpcb *)so->so_tcpcb) && 55 (tp->t_flags & TF_DELACK)) { 56 tp->t_flags &= ~TF_DELACK; 57 tp->t_flags |= TF_ACKNOW; 58 tcpstat.tcps_delack++; 59 (void) tcp_output(pData, tp); 60 } 54 if ( (tp = (struct tcpcb *)so->so_tcpcb) 55 && (tp->t_flags & TF_DELACK)) 56 { 57 tp->t_flags &= ~TF_DELACK; 58 tp->t_flags |= TF_ACKNOW; 59 tcpstat.tcps_delack++; 60 (void) tcp_output(pData, tp); 61 } 61 62 } 62 63 … … 69 70 tcp_slowtimo(PNATState pData) 70 71 { 71 register struct socket *ip, *ipnxt; 72 register struct tcpcb *tp; 73 register int i; 74 75 DEBUG_CALL("tcp_slowtimo"); 76 77 /* 78 * Search through tcb's and update active timers. 79 */ 80 ip = tcb.so_next; 81 if (ip == 0) 82 return; 83 for (; ip != &tcb; ip = ipnxt) { 84 ipnxt = ip->so_next; 85 tp = sototcpcb(ip); 86 if (tp == 0) 87 continue; 88 for (i = 0; i < TCPT_NTIMERS; i++) { 89 if (tp->t_timer[i] && --tp->t_timer[i] == 0) { 90 tcp_timers(pData, tp,i); 91 if (ipnxt->so_prev != ip) 92 goto tpgone; 93 } 94 } 95 tp->t_idle++; 96 if (tp->t_rtt) 97 tp->t_rtt++; 72 register struct socket *ip, *ipnxt; 73 register struct tcpcb *tp; 74 register int i; 75 76 DEBUG_CALL("tcp_slowtimo"); 77 78 /* 79 * Search through tcb's and update active timers. 80 */ 81 ip = tcb.so_next; 82 if (ip == 0) 83 return; 84 for (; ip != &tcb; ip = ipnxt) 85 { 86 ipnxt = ip->so_next; 87 tp = sototcpcb(ip); 88 if (tp == 0) 89 continue; 90 for (i = 0; i < TCPT_NTIMERS; i++) 91 { 92 if (tp->t_timer[i] && --tp->t_timer[i] == 0) 93 { 94 tcp_timers(pData, tp,i); 95 if (ipnxt->so_prev != ip) 96 goto tpgone; 97 } 98 } 99 tp->t_idle++; 100 if (tp->t_rtt) 101 tp->t_rtt++; 98 102 tpgone: 99 100 101 tcp_iss += TCP_ISSINCR/PR_SLOWHZ;/* increment iss */103 ; 104 } 105 tcp_iss += TCP_ISSINCR / PR_SLOWHZ; /* increment iss */ 102 106 #ifdef TCP_COMPAT_42 103 104 107 if ((int)tcp_iss < 0) 108 tcp_iss = 0; /* XXX */ 105 109 #endif 106 tcp_now++;/* for timestamps */110 tcp_now++; /* for timestamps */ 107 111 } 108 112 … … 111 115 */ 112 116 void 113 tcp_canceltimers(tp) 114 struct tcpcb *tp; 115 { 116 register int i; 117 118 for (i = 0; i < TCPT_NTIMERS; i++) 119 tp->t_timer[i] = 0; 117 tcp_canceltimers(struct tcpcb *tp) 118 { 119 register int i; 120 121 for (i = 0; i < TCPT_NTIMERS; i++) 122 tp->t_timer[i] = 0; 120 123 } 121 124 122 const int tcp_backoff[TCP_MAXRXTSHIFT + 1] = 123 { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 }; 125 const int tcp_backoff[TCP_MAXRXTSHIFT + 1] = 126 { 127 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 128 }; 124 129 125 130 /* … … 129 134 tcp_timers(PNATState pData, register struct tcpcb *tp, int timer) 130 135 { 131 132 133 134 135 switch (timer) {136 136 register int rexmt; 137 138 DEBUG_CALL("tcp_timers"); 139 140 switch (timer) 141 { 137 142 /* 138 143 * 2 MSL timeout in shutdown went off. If we're closed but … … 142 147 */ 143 148 case TCPT_2MSL: 144 149 if (tp->t_state != TCPS_TIME_WAIT && 145 150 tp->t_idle <= tcp_maxidle) 146 147 148 149 151 tp->t_timer[TCPT_2MSL] = tcp_keepintvl; 152 else 153 tp = tcp_close(pData, tp); 154 break; 150 155 151 156 /* … … 155 160 */ 156 161 case TCPT_REXMT: 157 162 /* 163 * XXX If a packet has timed out, then remove all the queued 164 * packets for that session. 165 */ 166 if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) 167 { 158 168 /* 159 * XXXXX If a packet has timed out, then remove all the queued 160 * packets for that session. 169 * This is a hack to suit our terminal server here at the uni of canberra 170 * since they have trouble with zeroes... It usually lets them through 171 * unharmed, but under some conditions, it'll eat the zeros. If we 172 * keep retransmitting it, it'll keep eating the zeroes, so we keep 173 * retransmitting, and eventually the connection dies... 174 * (this only happens on incoming data) 175 * 176 * So, if we were gonna drop the connection from too many retransmits, 177 * don't... instead halve the t_maxseg, which might break up the NULLs and 178 * let them through 179 * 180 * *sigh* 161 181 */ 162 163 if (++tp->t_rxtshift > TCP_MAXRXTSHIFT) { 164 /* 165 * This is a hack to suit our terminal server here at the uni of canberra 166 * since they have trouble with zeroes... It usually lets them through 167 * unharmed, but under some conditions, it'll eat the zeros. If we 168 * keep retransmitting it, it'll keep eating the zeroes, so we keep 169 * retransmitting, and eventually the connection dies... 170 * (this only happens on incoming data) 171 * 172 * So, if we were gonna drop the connection from too many retransmits, 173 * don't... instead halve the t_maxseg, which might break up the NULLs and 174 * let them through 175 * 176 * *sigh* 177 */ 178 179 tp->t_maxseg >>= 1; 180 if (tp->t_maxseg < 32) { 181 /* 182 * We tried our best, now the connection must die! 183 */ 184 tp->t_rxtshift = TCP_MAXRXTSHIFT; 185 tcpstat.tcps_timeoutdrop++; 186 tp = tcp_drop(pData, tp, tp->t_softerror); 187 /* tp->t_softerror : ETIMEDOUT); */ /* XXX */ 188 return (tp); /* XXX */ 189 } 190 191 /* 192 * Set rxtshift to 6, which is still at the maximum 193 * backoff time 194 */ 195 tp->t_rxtshift = 6; 182 tp->t_maxseg >>= 1; 183 if (tp->t_maxseg < 32) 184 { 185 /* 186 * We tried our best, now the connection must die! 187 */ 188 tp->t_rxtshift = TCP_MAXRXTSHIFT; 189 tcpstat.tcps_timeoutdrop++; 190 tp = tcp_drop(pData, tp, tp->t_softerror); 191 /* tp->t_softerror : ETIMEDOUT); */ /* XXX */ 192 return (tp); /* XXX */ 196 193 } 197 tcpstat.tcps_rexmttimeo++; 198 rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; 199 TCPT_RANGESET(tp->t_rxtcur, rexmt, 194 195 /* 196 * Set rxtshift to 6, which is still at the maximum 197 * backoff time 198 */ 199 tp->t_rxtshift = 6; 200 } 201 tcpstat.tcps_rexmttimeo++; 202 rexmt = TCP_REXMTVAL(tp) * tcp_backoff[tp->t_rxtshift]; 203 TCPT_RANGESET(tp->t_rxtcur, rexmt, 200 204 (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ 201 tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; 202 /* 203 * If losing, let the lower level know and try for 204 * a better route. Also, if we backed off this far, 205 * our srtt estimate is probably bogus. Clobber it 206 * so we'll take the next rtt measurement as our srtt; 207 * move the current srtt into rttvar to keep the current 208 * retransmit times until then. 209 */ 210 if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) { 211 /* in_losing(tp->t_inpcb); */ 212 tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT); 213 tp->t_srtt = 0; 214 } 215 tp->snd_nxt = tp->snd_una; 216 /* 217 * If timing a segment in this window, stop the timer. 218 */ 219 tp->t_rtt = 0; 220 /* 221 * Close the congestion window down to one segment 222 * (we'll open it by one segment for each ack we get). 223 * Since we probably have a window's worth of unacked 224 * data accumulated, this "slow start" keeps us from 225 * dumping all that data as back-to-back packets (which 226 * might overwhelm an intermediate gateway). 227 * 228 * There are two phases to the opening: Initially we 229 * open by one mss on each ack. This makes the window 230 * size increase exponentially with time. If the 231 * window is larger than the path can handle, this 232 * exponential growth results in dropped packet(s) 233 * almost immediately. To get more time between 234 * drops but still "push" the network to take advantage 235 * of improving conditions, we switch from exponential 236 * to linear window opening at some threshold size. 237 * For a threshold, we use half the current window 238 * size, truncated to a multiple of the mss. 239 * 240 * (the minimum cwnd that will give us exponential 241 * growth is 2 mss. We don't allow the threshold 242 * to go below this.) 243 */ 244 { 205 tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; 206 /* 207 * If losing, let the lower level know and try for 208 * a better route. Also, if we backed off this far, 209 * our srtt estimate is probably bogus. Clobber it 210 * so we'll take the next rtt measurement as our srtt; 211 * move the current srtt into rttvar to keep the current 212 * retransmit times until then. 213 */ 214 if (tp->t_rxtshift > TCP_MAXRXTSHIFT / 4) 215 { 216 /* in_losing(tp->t_inpcb); */ 217 tp->t_rttvar += (tp->t_srtt >> TCP_RTT_SHIFT); 218 tp->t_srtt = 0; 219 } 220 tp->snd_nxt = tp->snd_una; 221 /* 222 * If timing a segment in this window, stop the timer. 223 */ 224 tp->t_rtt = 0; 225 /* 226 * Close the congestion window down to one segment 227 * (we'll open it by one segment for each ack we get). 228 * Since we probably have a window's worth of unacked 229 * data accumulated, this "slow start" keeps us from 230 * dumping all that data as back-to-back packets (which 231 * might overwhelm an intermediate gateway). 232 * 233 * There are two phases to the opening: Initially we 234 * open by one mss on each ack. This makes the window 235 * size increase exponentially with time. If the 236 * window is larger than the path can handle, this 237 * exponential growth results in dropped packet(s) 238 * almost immediately. To get more time between 239 * drops but still "push" the network to take advantage 240 * of improving conditions, we switch from exponential 241 * to linear window opening at some threshold size. 242 * For a threshold, we use half the current window 243 * size, truncated to a multiple of the mss. 244 * 245 * (the minimum cwnd that will give us exponential 246 * growth is 2 mss. We don't allow the threshold 247 * to go below this.) 248 */ 249 { 245 250 u_int win = min(tp->snd_wnd, tp->snd_cwnd) / 2 / tp->t_maxseg; 246 251 if (win < 2) 247 252 win = 2; 248 253 tp->snd_cwnd = tp->t_maxseg; 249 254 tp->snd_ssthresh = win * tp->t_maxseg; 250 255 tp->t_dupacks = 0; 251 252 253 256 } 257 (void) tcp_output(pData, tp); 258 break; 254 259 255 260 /* … … 258 263 */ 259 264 case TCPT_PERSIST: 260 261 262 263 264 265 265 tcpstat.tcps_persisttimeo++; 266 tcp_setpersist(tp); 267 tp->t_force = 1; 268 (void) tcp_output(pData, tp); 269 tp->t_force = 0; 270 break; 266 271 267 272 /* … … 270 275 */ 271 276 case TCPT_KEEP: 272 tcpstat.tcps_keeptimeo++; 273 if (tp->t_state < TCPS_ESTABLISHED) 274 goto dropit; 275 276 /* if (tp->t_socket->so_options & SO_KEEPALIVE && */ 277 if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) { 278 if (tp->t_idle >= tcp_keepidle + tcp_maxidle) 279 goto dropit; 280 /* 281 * Send a packet designed to force a response 282 * if the peer is up and reachable: 283 * either an ACK if the connection is still alive, 284 * or an RST if the peer has closed the connection 285 * due to timeout or reboot. 286 * Using sequence number tp->snd_una-1 287 * causes the transmitted zero-length segment 288 * to lie outside the receive window; 289 * by the protocol spec, this requires the 290 * correspondent TCP to respond. 291 */ 292 tcpstat.tcps_keepprobe++; 277 tcpstat.tcps_keeptimeo++; 278 if (tp->t_state < TCPS_ESTABLISHED) 279 goto dropit; 280 /* if (tp->t_socket->so_options & SO_KEEPALIVE && */ 281 if ((so_options) && tp->t_state <= TCPS_CLOSE_WAIT) { 282 if (tp->t_idle >= tcp_keepidle + tcp_maxidle) 283 goto dropit; 284 /* 285 * Send a packet designed to force a response 286 * if the peer is up and reachable: 287 * either an ACK if the connection is still alive, 288 * or an RST if the peer has closed the connection 289 * due to timeout or reboot. 290 * Using sequence number tp->snd_una-1 291 * causes the transmitted zero-length segment 292 * to lie outside the receive window; 293 * by the protocol spec, this requires the 294 * correspondent TCP to respond. 295 */ 296 tcpstat.tcps_keepprobe++; 293 297 #ifdef TCP_COMPAT_42 294 295 296 297 298 298 /* 299 * The keepalive packet must have nonzero length 300 * to get a 4.2 host to respond. 301 */ 302 tcp_respond(tp, &tp->t_template, (struct mbuf *)NULL, 299 303 tp->rcv_nxt - 1, tp->snd_una - 1, 0); 300 304 #else 301 302 305 tcp_respond(pData, tp, &tp->t_template, (struct mbuf *)NULL, 306 tp->rcv_nxt, tp->snd_una - 1, 0); 303 307 #endif 304 tp->t_timer[TCPT_KEEP] = tcp_keepintvl; 305 } else 306 tp->t_timer[TCPT_KEEP] = tcp_keepidle; 307 break; 308 tp->t_timer[TCPT_KEEP] = tcp_keepintvl; 309 } 310 else 311 tp->t_timer[TCPT_KEEP] = tcp_keepidle; 312 break; 308 313 309 314 dropit: 310 311 312 313 314 315 return (tp);315 tcpstat.tcps_keepdrops++; 316 tp = tcp_drop(pData, tp, 0); /* ETIMEDOUT); */ 317 break; 318 } 319 320 return tp; 316 321 } -
trunk/src/VBox/Devices/Network/slirp/tcp_timer.h
r14470 r14964 103 103 104 104 #define TCPTV_MIN ( 1*PR_SLOWHZ) /* minimum allowable value */ 105 /* #define TCPTV_REXMTMAX ( 64*PR_SLOWHZ) */ /* max allowable REXMT value */106 105 #define TCPTV_REXMTMAX ( 12*PR_SLOWHZ) /* max allowable REXMT value */ 107 106 -
trunk/src/VBox/Devices/Network/slirp/tcpip.h
r1 r14964 41 41 * Tcp+ip header, after ip options removed. 42 42 */ 43 struct tcpiphdr { 44 struct ipovly ti_i; /* overlaid ip structure */ 45 struct tcphdr ti_t; /* tcp header */ 43 struct tcpiphdr 44 { 45 struct ipovly ti_i; /* overlaid ip structure */ 46 struct tcphdr ti_t; /* tcp header */ 46 47 }; 47 48 #define ti_next ti_i.ih_next … … 67 68 * of the packet 68 69 */ 69 struct tcpiphdr_2 { 70 struct tcpiphdr dummy; 71 char first_char; 70 struct tcpiphdr_2 71 { 72 struct tcpiphdr dummy; 73 char first_char; 72 74 }; 73 75 -
trunk/src/VBox/Devices/Network/slirp/tftp.c
r14470 r14964 34 34 static void tftp_session_terminate(struct tftp_session *spt) 35 35 { 36 spt->in_use = 0;36 spt->in_use = 0; 37 37 } 38 38 39 39 static int tftp_session_allocate(PNATState pData, struct tftp_t *tp) 40 40 { 41 struct tftp_session *spt; 42 int k; 43 44 for (k = 0; k < TFTP_SESSIONS_MAX; k++) { 45 spt = &tftp_sessions[k]; 46 47 if (!spt->in_use) 48 goto found; 49 50 /* sessions time out after 5 inactive seconds */ 51 if ((int)(curtime - spt->timestamp) > 5000) 52 goto found; 53 } 54 55 return -1; 41 struct tftp_session *spt; 42 int k; 43 44 for (k = 0; k < TFTP_SESSIONS_MAX; k++) 45 { 46 spt = &tftp_sessions[k]; 47 48 if (!spt->in_use) 49 goto found; 50 51 /* sessions time out after 5 inactive seconds */ 52 if ((int)(curtime - spt->timestamp) > 5000) 53 goto found; 54 } 55 56 return -1; 56 57 57 58 found: 58 memset(spt, 0, sizeof(*spt));59 memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip));60 spt->client_port = tp->udp.uh_sport;61 62 tftp_session_update(pData, spt);63 64 return k;59 memset(spt, 0, sizeof(*spt)); 60 memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); 61 spt->client_port = tp->udp.uh_sport; 62 63 tftp_session_update(pData, spt); 64 65 return k; 65 66 } 66 67 67 68 static int tftp_session_find(PNATState pData, struct tftp_t *tp) 68 69 { 69 struct tftp_session *spt; 70 int k; 71 72 for (k = 0; k < TFTP_SESSIONS_MAX; k++) { 73 spt = &tftp_sessions[k]; 74 75 if (spt->in_use) { 76 if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) { 77 if (spt->client_port == tp->udp.uh_sport) { 78 return k; 70 struct tftp_session *spt; 71 int k; 72 73 for (k = 0; k < TFTP_SESSIONS_MAX; k++) 74 { 75 spt = &tftp_sessions[k]; 76 77 if (spt->in_use) 78 { 79 if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) 80 { 81 if (spt->client_port == tp->udp.uh_sport) 82 return k; 83 } 79 84 } 80 } 81 } 82 } 83 84 return -1; 85 } 86 87 return -1; 85 88 } 86 89 … … 88 91 u_int8_t *buf, int len) 89 92 { 90 int fd; 91 int bytes_read = 0; 92 char buffer[1024]; 93 int n; 94 95 n = RTStrPrintf(buffer, sizeof(buffer), "%s/%s", 96 tftp_prefix, spt->filename); 97 if (n >= sizeof(buffer)) 98 return -1; 99 100 fd = open(buffer, O_RDONLY | O_BINARY); 101 102 if (fd < 0) { 103 return -1; 104 } 105 106 if (len) { 107 lseek(fd, block_nr * 512, SEEK_SET); 108 109 bytes_read = read(fd, buf, len); 110 } 111 112 close(fd); 113 114 return bytes_read; 93 int fd; 94 int bytes_read = 0; 95 char buffer[1024]; 96 int n; 97 98 n = RTStrPrintf(buffer, sizeof(buffer), "%s/%s", 99 tftp_prefix, spt->filename); 100 if (n >= sizeof(buffer)) 101 return -1; 102 103 fd = open(buffer, O_RDONLY | O_BINARY); 104 if (fd < 0) 105 return -1; 106 107 if (len) 108 { 109 lseek(fd, block_nr * 512, SEEK_SET); 110 bytes_read = read(fd, buf, len); 111 } 112 113 close(fd); 114 115 return bytes_read; 115 116 } 116 117 … … 126 127 127 128 m = m_get(pData); 128 129 129 if (!m) 130 130 return -1; … … 160 160 struct tftp_t *recv_tp) 161 161 { 162 struct sockaddr_in saddr, daddr; 163 struct mbuf *m; 164 struct tftp_t *tp; 165 int nobytes; 166 167 m = m_get(pData); 168 169 if (!m) { 170 return -1; 171 } 172 173 memset(m->m_data, 0, m->m_size); 174 175 m->m_data += if_maxlinkhdr; 176 tp = (void *)m->m_data; 177 m->m_data += sizeof(struct udpiphdr); 178 179 tp->tp_op = htons(TFTP_ERROR); 180 tp->x.tp_error.tp_error_code = htons(errorcode); 181 strcpy((char *)tp->x.tp_error.tp_msg, msg); 182 183 saddr.sin_addr = recv_tp->ip.ip_dst; 184 saddr.sin_port = recv_tp->udp.uh_dport; 185 186 daddr.sin_addr = spt->client_ip; 187 daddr.sin_port = spt->client_port; 188 189 nobytes = 2; 190 191 m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg) - 192 sizeof(struct ip) - sizeof(struct udphdr); 193 194 udp_output2(pData, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); 195 196 tftp_session_terminate(spt); 197 198 return 0; 162 struct sockaddr_in saddr, daddr; 163 struct mbuf *m; 164 struct tftp_t *tp; 165 int nobytes; 166 167 m = m_get(pData); 168 if (!m) 169 return -1; 170 171 memset(m->m_data, 0, m->m_size); 172 173 m->m_data += if_maxlinkhdr; 174 tp = (void *)m->m_data; 175 m->m_data += sizeof(struct udpiphdr); 176 177 tp->tp_op = htons(TFTP_ERROR); 178 tp->x.tp_error.tp_error_code = htons(errorcode); 179 strcpy((char *)tp->x.tp_error.tp_msg, msg); 180 181 saddr.sin_addr = recv_tp->ip.ip_dst; 182 saddr.sin_port = recv_tp->udp.uh_dport; 183 184 daddr.sin_addr = spt->client_ip; 185 daddr.sin_port = spt->client_port; 186 187 nobytes = 2; 188 189 m->m_len = sizeof(struct tftp_t) 190 - 514 191 + 3 192 + strlen(msg) 193 - sizeof(struct ip) 194 - sizeof(struct udphdr); 195 196 udp_output2(pData, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); 197 198 tftp_session_terminate(spt); 199 200 return 0; 199 201 } 200 202 … … 204 206 struct tftp_t *recv_tp) 205 207 { 206 struct sockaddr_in saddr, daddr; 207 struct mbuf *m; 208 struct tftp_t *tp; 209 int nobytes; 210 211 if (block_nr < 1) { 212 return -1; 213 } 214 215 m = m_get(pData); 216 217 if (!m) { 218 return -1; 219 } 220 221 memset(m->m_data, 0, m->m_size); 222 223 m->m_data += if_maxlinkhdr; 224 tp = (void *)m->m_data; 225 m->m_data += sizeof(struct udpiphdr); 226 227 tp->tp_op = htons(TFTP_DATA); 228 tp->x.tp_data.tp_block_nr = htons(block_nr); 229 230 saddr.sin_addr = recv_tp->ip.ip_dst; 231 saddr.sin_port = recv_tp->udp.uh_dport; 232 233 daddr.sin_addr = spt->client_ip; 234 daddr.sin_port = spt->client_port; 235 236 nobytes = tftp_read_data(pData, spt, block_nr - 1, tp->x.tp_data.tp_buf, 512); 237 238 if (nobytes < 0) { 239 m_free(pData, m); 240 241 /* send "file not found" error back */ 242 243 tftp_send_error(pData, spt, 1, "File not found", tp); 244 245 return -1; 246 } 247 248 m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - 249 sizeof(struct ip) - sizeof(struct udphdr); 250 251 udp_output2(pData, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); 252 253 if (nobytes == 512) { 254 tftp_session_update(pData, spt); 255 } 256 else { 257 tftp_session_terminate(spt); 258 } 259 260 return 0; 208 struct sockaddr_in saddr, daddr; 209 struct mbuf *m; 210 struct tftp_t *tp; 211 int nobytes; 212 213 if (block_nr < 1) 214 return -1; 215 216 m = m_get(pData); 217 if (!m) 218 return -1; 219 220 memset(m->m_data, 0, m->m_size); 221 222 m->m_data += if_maxlinkhdr; 223 tp = (void *)m->m_data; 224 m->m_data += sizeof(struct udpiphdr); 225 226 tp->tp_op = htons(TFTP_DATA); 227 tp->x.tp_data.tp_block_nr = htons(block_nr); 228 229 saddr.sin_addr = recv_tp->ip.ip_dst; 230 saddr.sin_port = recv_tp->udp.uh_dport; 231 232 daddr.sin_addr = spt->client_ip; 233 daddr.sin_port = spt->client_port; 234 235 nobytes = tftp_read_data(pData, spt, block_nr - 1, tp->x.tp_data.tp_buf, 512); 236 if (nobytes < 0) 237 { 238 m_free(pData, m); 239 /* send "file not found" error back */ 240 tftp_send_error(pData, spt, 1, "File not found", tp); 241 return -1; 242 } 243 244 m->m_len = sizeof(struct tftp_t) 245 - (512 - nobytes) 246 - sizeof(struct ip) 247 - sizeof(struct udphdr); 248 249 udp_output2(pData, NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); 250 251 if (nobytes == 512) 252 tftp_session_update(pData, spt); 253 else 254 tftp_session_terminate(spt); 255 256 return 0; 261 257 } 262 258 263 259 static void tftp_handle_rrq(PNATState pData, struct tftp_t *tp, int pktlen) 264 260 { 265 struct tftp_session *spt; 266 int s, k, n; 267 u_int8_t *src, *dst; 268 269 s = tftp_session_allocate(pData, tp); 270 271 if (s < 0) { 272 return; 273 } 274 275 spt = &tftp_sessions[s]; 276 277 src = tp->x.tp_buf; 278 dst = spt->filename; 279 n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp); 280 281 /* get name */ 282 283 for (k = 0; k < n; k++) { 284 if (k < TFTP_FILENAME_MAX) { 285 dst[k] = src[k]; 286 } 287 else { 288 return; 289 } 290 291 if (src[k] == '\0') { 292 break; 293 } 294 } 295 296 if (k >= n) { 297 return; 298 } 299 300 k++; 301 302 /* check mode */ 303 if ((n - k) < 6) { 304 return; 305 } 306 307 if (memcmp(&src[k], "octet\0", 6) != 0) { 308 tftp_send_error(pData, spt, 4, "Unsupported transfer mode", tp); 309 return; 310 } 311 312 k += 6; /* skipping octet */ 313 314 /* do sanity checks on the filename */ 315 316 if ( !strncmp((const char*)spt->filename, "../", 3) 317 || (spt->filename[strlen((const char *)spt->filename) - 1] == '/') 318 || strstr((const char *)spt->filename, "/../")) { 319 tftp_send_error(pData, spt, 2, "Access violation", tp); 320 return; 321 } 322 323 /* only allow exported prefixes */ 324 325 if (!tftp_prefix) { 326 tftp_send_error(pData, spt, 2, "Access violation", tp); 327 return; 328 } 329 330 /* check if the file exists */ 331 332 if (tftp_read_data(pData, spt, 0, spt->filename, 0) < 0) { 333 tftp_send_error(pData, spt, 1, "File not found", tp); 334 return; 335 } 336 337 if (src[n - 1] != 0) { 338 tftp_send_error(pData, spt, 2, "Access violation", tp); 339 return; 340 } 341 342 while (k < n) { 343 const char *key, *value; 344 345 key = (const char *)src + k; 346 k += strlen(key) + 1; 347 348 if (k >= n) { 349 tftp_send_error(pData, spt, 2, "Access violation", tp); 350 return; 351 } 352 353 value = (const char *)src + k; 354 k += strlen(value) + 1; 355 356 if (strcmp(key, "tsize") == 0) { 357 int tsize = atoi(value); 358 struct stat stat_p; 359 360 if (tsize == 0 && tftp_prefix) { 361 char buffer[1024]; 362 int len; 363 364 len = RTStrPrintf(buffer, sizeof(buffer), "%s/%s", 365 tftp_prefix, spt->filename); 366 367 if (stat(buffer, &stat_p) == 0) 368 tsize = stat_p.st_size; 369 else { 370 tftp_send_error(pData, spt, 1, "File not found", tp); 371 return; 372 } 373 } 374 375 tftp_send_oack(pData, spt, "tsize", tsize, tp); 376 } 377 } 378 379 tftp_send_data(pData, spt, 1, tp); 261 struct tftp_session *spt; 262 int s, k, n; 263 u_int8_t *src, *dst; 264 265 s = tftp_session_allocate(pData, tp); 266 if (s < 0) 267 return; 268 269 spt = &tftp_sessions[s]; 270 271 src = tp->x.tp_buf; 272 dst = spt->filename; 273 n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp); 274 275 /* get name */ 276 for (k = 0; k < n; k++) 277 { 278 if (k < TFTP_FILENAME_MAX) 279 dst[k] = src[k]; 280 else 281 return; 282 283 if (src[k] == '\0') 284 break; 285 } 286 287 if (k >= n) 288 return; 289 290 k++; 291 292 /* check mode */ 293 if ((n - k) < 6) 294 return; 295 296 if (memcmp(&src[k], "octet\0", 6) != 0) 297 { 298 tftp_send_error(pData, spt, 4, "Unsupported transfer mode", tp); 299 return; 300 } 301 302 k += 6; /* skipping octet */ 303 304 /* do sanity checks on the filename */ 305 if ( !strncmp((const char*)spt->filename, "../", 3) 306 || (spt->filename[strlen((const char *)spt->filename) - 1] == '/') 307 || strstr((const char *)spt->filename, "/../")) { 308 tftp_send_error(pData, spt, 2, "Access violation", tp); 309 return; 310 } 311 312 /* only allow exported prefixes */ 313 if (!tftp_prefix) 314 { 315 tftp_send_error(pData, spt, 2, "Access violation", tp); 316 return; 317 } 318 319 /* check if the file exists */ 320 if (tftp_read_data(pData, spt, 0, spt->filename, 0) < 0) 321 { 322 tftp_send_error(pData, spt, 1, "File not found", tp); 323 return; 324 } 325 326 if (src[n - 1] != 0) 327 { 328 tftp_send_error(pData, spt, 2, "Access violation", tp); 329 return; 330 } 331 332 while (k < n) 333 { 334 const char *key, *value; 335 336 key = (const char *)src + k; 337 k += strlen(key) + 1; 338 339 if (k >= n) 340 { 341 tftp_send_error(pData, spt, 2, "Access violation", tp); 342 return; 343 } 344 345 value = (const char *)src + k; 346 k += strlen(value) + 1; 347 348 if (strcmp(key, "tsize") == 0) 349 { 350 int tsize = atoi(value); 351 struct stat stat_p; 352 353 if (tsize == 0 && tftp_prefix) 354 { 355 char buffer[1024]; 356 int len; 357 358 len = RTStrPrintf(buffer, sizeof(buffer), "%s/%s", 359 tftp_prefix, spt->filename); 360 if (stat(buffer, &stat_p) == 0) 361 tsize = stat_p.st_size; 362 else 363 { 364 tftp_send_error(pData, spt, 1, "File not found", tp); 365 return; 366 } 367 } 368 369 tftp_send_oack(pData, spt, "tsize", tsize, tp); 370 } 371 } 372 373 tftp_send_data(pData, spt, 1, tp); 380 374 } 381 375 382 376 static void tftp_handle_ack(PNATState pData, struct tftp_t *tp, int pktlen) 383 377 { 384 int s; 385 386 s = tftp_session_find(pData, tp); 387 388 if (s < 0) { 389 return; 390 } 391 392 if (tftp_send_data(pData, &tftp_sessions[s], 393 ntohs(tp->x.tp_data.tp_block_nr) + 1, 394 tp) < 0) { 395 return; 396 } 378 int s; 379 380 s = tftp_session_find(pData, tp); 381 if (s < 0) 382 return; 383 384 if (tftp_send_data(pData, &tftp_sessions[s], 385 ntohs(tp->x.tp_data.tp_block_nr) + 1, tp) < 0) 386 { 387 /* XXX */ 388 } 397 389 } 398 390 399 391 void tftp_input(PNATState pData, struct mbuf *m) 400 392 { 401 struct tftp_t *tp = (struct tftp_t *)m->m_data; 402 403 switch(ntohs(tp->tp_op)) { 404 case TFTP_RRQ: 405 tftp_handle_rrq(pData, tp, m->m_len); 406 break; 407 408 case TFTP_ACK: 409 tftp_handle_ack(pData, tp, m->m_len); 410 break; 411 } 412 } 393 struct tftp_t *tp = (struct tftp_t *)m->m_data; 394 395 switch(ntohs(tp->tp_op)) 396 { 397 case TFTP_RRQ: 398 tftp_handle_rrq(pData, tp, m->m_len); 399 break; 400 401 case TFTP_ACK: 402 tftp_handle_ack(pData, tp, m->m_len); 403 break; 404 } 405 } -
trunk/src/VBox/Devices/Network/slirp/tftp.h
r14470 r14964 14 14 #define TFTP_FILENAME_MAX 512 15 15 16 struct tftp_t { 17 struct ip ip; 18 struct udphdr udp; 19 u_int16_t tp_op; 20 union { 21 struct { 22 u_int16_t tp_block_nr; 23 u_int8_t tp_buf[512]; 24 } tp_data; 25 struct { 26 u_int16_t tp_error_code; 27 u_int8_t tp_msg[512]; 28 } tp_error; 29 u_int8_t tp_buf[512 + 2]; 30 } x; 16 struct tftp_t 17 { 18 struct ip ip; 19 struct udphdr udp; 20 u_int16_t tp_op; 21 union 22 { 23 struct 24 { 25 u_int16_t tp_block_nr; 26 u_int8_t tp_buf[512]; 27 } tp_data; 28 struct 29 { 30 u_int16_t tp_error_code; 31 u_int8_t tp_msg[512]; 32 } tp_error; 33 u_int8_t tp_buf[512 + 2]; 34 } x; 31 35 }; 32 36
Note:
See TracChangeset
for help on using the changeset viewer.