Changes in uspace/srv/net/inetsrv/pdu.c [1d24ad3:a1a101d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/net/inetsrv/pdu.c
r1d24ad3 ra1a101d 44 44 #include <mem.h> 45 45 #include <stdlib.h> 46 #include <net/socket_codes.h> 46 47 47 #include "inetsrv.h" 48 48 #include "inet_std.h" … … 106 106 void **rdata, size_t *rsize, size_t *roffs) 107 107 { 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 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 119 122 /* Upper bound for fragment offset field */ 120 size_tfragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);121 123 fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l); 124 122 125 /* Verify that total size of datagram is within reasonable bounds */ 123 126 if (offs + packet->size > FRAG_OFFS_UNIT * fragoff_limit) 124 127 return ELIMIT; 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 128 129 hdr_size = sizeof(ip_header_t); 130 data_offs = ROUND_UP(hdr_size, 4); 131 141 132 assert(offs % FRAG_OFFS_UNIT == 0); 142 133 assert(offs / FRAG_OFFS_UNIT < fragoff_limit); 143 134 144 135 /* Value for the fragment offset field */ 145 uint16_tfoff = offs / FRAG_OFFS_UNIT;146 136 foff = offs / FRAG_OFFS_UNIT; 137 147 138 if (hdr_size >= mtu) 148 139 return EINVAL; 149 140 150 141 /* Amount of space in the PDU available for payload */ 151 s ize_t spc_avail = mtu - hdr_size;142 spc_avail = mtu - hdr_size; 152 143 spc_avail -= (spc_avail % FRAG_OFFS_UNIT); 153 144 154 145 /* Amount of data (payload) to transfer */ 155 size_txfer_size = min(packet->size - offs, spc_avail);156 146 xfer_size = min(packet->size - offs, spc_avail); 147 157 148 /* Total PDU size */ 158 size _t size= hdr_size + xfer_size;159 149 size = hdr_size + xfer_size; 150 160 151 /* Offset of remaining payload */ 161 size_trem_offs = offs + xfer_size;162 152 rem_offs = offs + xfer_size; 153 163 154 /* Flags */ 164 uint16_tflags_foff =155 flags_foff = 165 156 (packet->df ? BIT_V(uint16_t, FF_FLAG_DF) : 0) + 166 157 (rem_offs < packet->size ? BIT_V(uint16_t, FF_FLAG_MF) : 0) + 167 158 (foff << FF_FRAGOFF_l); 168 169 void *data = calloc(size, 1);159 160 data = calloc(size, 1); 170 161 if (data == NULL) 171 162 return ENOMEM; 172 163 173 164 /* Allocate identifier */ 174 165 fibril_mutex_lock(&ip_ident_lock); 175 uint16_tident = ++ip_ident;166 ident = ++ip_ident; 176 167 fibril_mutex_unlock(&ip_ident_lock); 177 168 178 169 /* Encode header fields */ 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 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 223 186 /* Copy payload */ 224 memcpy((uint8_t *) 225 187 memcpy((uint8_t *)data + data_offs, packet->data + offs, xfer_size); 188 226 189 *rdata = data; 227 190 *rsize = size; 228 191 *roffs = rem_offs; 229 192 230 193 return EOK; 231 194 } … … 233 196 int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet) 234 197 { 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 235 206 log_msg(LOG_DEFAULT, LVL_DEBUG, "inet_pdu_decode()"); 236 207 237 208 if (size < sizeof(ip_header_t)) { 238 209 log_msg(LOG_DEFAULT, LVL_DEBUG, "PDU too short (%zu)", size); 239 210 return EINVAL; 240 211 } 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);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); 246 217 if (version != 4) { 247 218 log_msg(LOG_DEFAULT, LVL_DEBUG, "Version (%d) != 4", version); 248 219 return EINVAL; 249 220 } 250 251 size_ttot_len = uint16_t_be2host(hdr->tot_len);221 222 tot_len = uint16_t_be2host(hdr->tot_len); 252 223 if (tot_len < sizeof(ip_header_t)) { 253 224 log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length too small (%zu)", tot_len); 254 225 return EINVAL; 255 226 } 256 227 257 228 if (tot_len > size) { 258 229 log_msg(LOG_DEFAULT, LVL_DEBUG, "Total Length = %zu > PDU size = %zu", … … 260 231 return EINVAL; 261 232 } 262 263 uint16_tident = uint16_t_be2host(hdr->id);264 uint16_tflags_foff = uint16_t_be2host(hdr->flags_foff);265 uint16_tfoff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l,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, 266 237 flags_foff); 267 238 /* XXX Checksum */ 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);239 240 packet->src.ipv4 = uint32_t_be2host(hdr->src_addr); 241 packet->dest.ipv4 = uint32_t_be2host(hdr->dest_addr); 271 242 packet->tos = hdr->tos; 272 243 packet->proto = hdr->proto; 273 244 packet->ttl = hdr->ttl; 274 245 packet->ident = ident; 275 246 276 247 packet->df = (flags_foff & BIT_V(uint16_t, FF_FLAG_DF)) != 0; 277 248 packet->mf = (flags_foff & BIT_V(uint16_t, FF_FLAG_MF)) != 0; 278 249 packet->offs = foff * FRAG_OFFS_UNIT; 279 250 280 251 /* XXX IP options */ 281 size_t data_offs = sizeof(uint32_t) *282 BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h,VI_IHL_l, hdr->ver_ihl);283 252 data_offs = sizeof(uint32_t) * BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h, 253 VI_IHL_l, hdr->ver_ihl); 254 284 255 packet->size = tot_len - data_offs; 285 256 packet->data = calloc(packet->size, 1); … … 288 259 return ENOMEM; 289 260 } 290 291 memcpy(packet->data, (uint8_t *) 292 261 262 memcpy(packet->data, (uint8_t *)data + data_offs, packet->size); 263 293 264 return EOK; 294 265 } 295 266 296 int inet_pdu_decode6(void *data, size_t size, inet_packet_t *packet)297 {298 // FIXME TODO299 return ENOTSUP;300 }301 302 267 /** @} 303 268 */
Note:
See TracChangeset
for help on using the changeset viewer.