Changes in uspace/srv/net/inetsrv/pdu.c [a1a101d:1d24ad3] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/inetsrv/pdu.c
ra1a101d r1d24ad3 44 44 #include <mem.h> 45 45 #include <stdlib.h> 46 46 #include <net/socket_codes.h> 47 47 #include "inetsrv.h" 48 48 #include "inet_std.h" … … 106 106 void **rdata, size_t *rsize, size_t *roffs) 107 107 { 108 void *data; 109 size_t size; 110 ip_header_t *hdr; 111 size_t hdr_size; 112 size_t data_offs; 113 uint16_t chksum; 114 uint16_t ident; 115 uint16_t flags_foff; 116 uint16_t foff; 117 size_t fragoff_limit; 118 size_t xfer_size; 119 size_t spc_avail; 120 size_t rem_offs; 121 108 addr32_t src_v4; 109 addr128_t src_v6; 110 uint16_t src_af = inet_addr_get(&packet->src, &src_v4, &src_v6); 111 112 addr32_t dest_v4; 113 addr128_t dest_v6; 114 uint16_t dest_af = inet_addr_get(&packet->dest, &dest_v4, &dest_v6); 115 116 if (src_af != dest_af) 117 return EINVAL; 118 122 119 /* Upper bound for fragment offset field */ 123 fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);124 120 size_t fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l); 121 125 122 /* Verify that total size of datagram is within reasonable bounds */ 126 123 if (offs + packet->size > FRAG_OFFS_UNIT * fragoff_limit) 127 124 return ELIMIT; 128 129 hdr_size = sizeof(ip_header_t); 130 data_offs = ROUND_UP(hdr_size, 4); 131 125 126 size_t hdr_size; 127 128 switch (src_af) { 129 case AF_INET: 130 hdr_size = sizeof(ip_header_t); 131 break; 132 case AF_INET6: 133 hdr_size = sizeof(ip6_header_t); 134 break; 135 default: 136 assert(false); 137 } 138 139 size_t data_offs = ROUND_UP(hdr_size, 4); 140 132 141 assert(offs % FRAG_OFFS_UNIT == 0); 133 142 assert(offs / FRAG_OFFS_UNIT < fragoff_limit); 134 143 135 144 /* Value for the fragment offset field */ 136 foff = offs / FRAG_OFFS_UNIT;137 145 uint16_t foff = offs / FRAG_OFFS_UNIT; 146 138 147 if (hdr_size >= mtu) 139 148 return EINVAL; 140 149 141 150 /* Amount of space in the PDU available for payload */ 142 s pc_avail = mtu - hdr_size;151 size_t spc_avail = mtu - hdr_size; 143 152 spc_avail -= (spc_avail % FRAG_OFFS_UNIT); 144 153 145 154 /* Amount of data (payload) to transfer */ 146 xfer_size = min(packet->size - offs, spc_avail);147 155 size_t xfer_size = min(packet->size - offs, spc_avail); 156 148 157 /* Total PDU size */ 149 size = hdr_size + xfer_size;150 158 size_t size = hdr_size + xfer_size; 159 151 160 /* Offset of remaining payload */ 152 rem_offs = offs + xfer_size;153 161 size_t rem_offs = offs + xfer_size; 162 154 163 /* Flags */ 155 flags_foff =164 uint16_t flags_foff = 156 165 (packet->df ? BIT_V(uint16_t, FF_FLAG_DF) : 0) + 157 166 (rem_offs < packet->size ? BIT_V(uint16_t, FF_FLAG_MF) : 0) + 158 167 (foff << FF_FRAGOFF_l); 159 160 data = calloc(size, 1);168 169 void *data = calloc(size, 1); 161 170 if (data == NULL) 162 171 return ENOMEM; 163 172 164 173 /* Allocate identifier */ 165 174 fibril_mutex_lock(&ip_ident_lock); 166 ident = ++ip_ident;175 uint16_t ident = ++ip_ident; 167 176 fibril_mutex_unlock(&ip_ident_lock); 168 177 169 178 /* Encode header fields */ 170 hdr = (ip_header_t *)data; 171 hdr->ver_ihl = (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t)); 172 hdr->tos = packet->tos; 173 hdr->tot_len = host2uint16_t_be(size); 174 hdr->id = host2uint16_t_be(ident); 175 hdr->flags_foff = host2uint16_t_be(flags_foff); 176 hdr->ttl = packet->ttl; 177 hdr->proto = packet->proto; 178 hdr->chksum = 0; 179 hdr->src_addr = host2uint32_t_be(packet->src.ipv4); 180 hdr->dest_addr = host2uint32_t_be(packet->dest.ipv4); 181 182 /* Compute checksum */ 183 chksum = inet_checksum_calc(INET_CHECKSUM_INIT, (void *)hdr, hdr_size); 184 hdr->chksum = host2uint16_t_be(chksum); 185 179 ip_header_t *hdr; 180 ip6_header_t *hdr6; 181 182 switch (src_af) { 183 case AF_INET: 184 hdr = (ip_header_t *) data; 185 186 hdr->ver_ihl = 187 (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t)); 188 hdr->tos = packet->tos; 189 hdr->tot_len = host2uint16_t_be(size); 190 hdr->id = host2uint16_t_be(ident); 191 hdr->flags_foff = host2uint16_t_be(flags_foff); 192 hdr->ttl = packet->ttl; 193 hdr->proto = packet->proto; 194 hdr->chksum = 0; 195 hdr->src_addr = host2uint32_t_be(src_v4); 196 hdr->dest_addr = host2uint32_t_be(dest_v4); 197 198 /* Compute checksum */ 199 uint16_t chksum = inet_checksum_calc(INET_CHECKSUM_INIT, 200 (void *) hdr, hdr_size); 201 hdr->chksum = host2uint16_t_be(chksum); 202 203 break; 204 case AF_INET6: 205 // TODO FIXME: fragmentation 206 207 hdr6 = (ip6_header_t *) data; 208 209 hdr6->ver_tc = (6 << (VI_VERSION_l)); 210 memset(hdr6->tc_fl, 0, 3); 211 hdr6->payload_len = host2uint16_t_be(packet->size); 212 hdr6->next = packet->proto; 213 hdr6->hop_limit = packet->ttl; 214 215 host2addr128_t_be(src_v6, hdr6->src_addr); 216 host2addr128_t_be(dest_v6, hdr6->dest_addr); 217 218 break; 219 default: 220 assert(false); 221 } 222 186 223 /* Copy payload */ 187 memcpy((uint8_t *) data + data_offs, packet->data + offs, xfer_size);188 224 memcpy((uint8_t *) data + data_offs, packet->data + offs, xfer_size); 225 189 226 *rdata = data; 190 227 *rsize = size; 191 228 *roffs = rem_offs; 192 229 193 230 return EOK; 194 231 } … … 196 233 int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet) 197 234 { 198 ip_header_t *hdr;199 size_t tot_len;200 size_t data_offs;201 uint8_t version;202 uint16_t ident;203 uint16_t flags_foff;204 uint16_t foff;205 206 235 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_pdu_decode()"); 207 236 208 237 if (size < sizeof(ip_header_t)) { 209 238 log_msg(LOG_DEFAULT, LVL_DEBUG, "PDU too short (%zu)", size); 210 239 return EINVAL; 211 240 } 212 213 hdr = (ip_header_t *)data;214 215 version = BIT_RANGE_EXTRACT(uint8_t, VI_VERSION_h, VI_VERSION_l,216 hdr->ver_ihl);241 242 ip_header_t *hdr = (ip_header_t *) data; 243 244 uint8_t version = BIT_RANGE_EXTRACT(uint8_t, VI_VERSION_h, 245 VI_VERSION_l, hdr->ver_ihl); 217 246 if (version != 4) { 218 247 log_msg(LOG_DEFAULT, LVL_DEBUG, "Version (%d) != 4", version); 219 248 return EINVAL; 220 249 } 221 222 tot_len = uint16_t_be2host(hdr->tot_len);250 251 size_t tot_len = uint16_t_be2host(hdr->tot_len); 223 252 if (tot_len < sizeof(ip_header_t)) { 224 253 log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length too small (%zu)", tot_len); 225 254 return EINVAL; 226 255 } 227 256 228 257 if (tot_len > size) { 229 258 log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length = %zu > PDU size = %zu", … … 231 260 return EINVAL; 232 261 } 233 234 ident = uint16_t_be2host(hdr->id);235 flags_foff = uint16_t_be2host(hdr->flags_foff);236 foff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l,262 263 uint16_t ident = uint16_t_be2host(hdr->id); 264 uint16_t flags_foff = uint16_t_be2host(hdr->flags_foff); 265 uint16_t foff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l, 237 266 flags_foff); 238 267 /* XXX Checksum */ 239 240 packet->src.ipv4 = uint32_t_be2host(hdr->src_addr);241 packet->dest.ipv4 = uint32_t_be2host(hdr->dest_addr);268 269 inet_addr_set(uint32_t_be2host(hdr->src_addr), &packet->src); 270 inet_addr_set(uint32_t_be2host(hdr->dest_addr), &packet->dest); 242 271 packet->tos = hdr->tos; 243 272 packet->proto = hdr->proto; 244 273 packet->ttl = hdr->ttl; 245 274 packet->ident = ident; 246 275 247 276 packet->df = (flags_foff & BIT_V(uint16_t, FF_FLAG_DF)) != 0; 248 277 packet->mf = (flags_foff & BIT_V(uint16_t, FF_FLAG_MF)) != 0; 249 278 packet->offs = foff * FRAG_OFFS_UNIT; 250 279 251 280 /* XXX IP options */ 252 data_offs = sizeof(uint32_t) * BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h,253 VI_IHL_l, hdr->ver_ihl);254 281 size_t data_offs = sizeof(uint32_t) * 282 BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h, VI_IHL_l, hdr->ver_ihl); 283 255 284 packet->size = tot_len - data_offs; 256 285 packet->data = calloc(packet->size, 1); … … 259 288 return ENOMEM; 260 289 } 261 262 memcpy(packet->data, (uint8_t *) data + data_offs, packet->size);263 290 291 memcpy(packet->data, (uint8_t *) data + data_offs, packet->size); 292 264 293 return EOK; 265 294 } 266 295 296 int inet_pdu_decode6(void *data, size_t size, inet_packet_t *packet) 297 { 298 // FIXME TODO 299 return ENOTSUP; 300 } 301 267 302 /** @} 268 303 */
Note:
See TracChangeset
for help on using the changeset viewer.