6 #include <net/netpacket.h>
8 //#define NETPACKET_DEBUG
10 /* these are just wrappers and handlers for memory etc.
11 * should contain no code that talks to hw
15 #ifdef NETPACKET_DEBUG
16 #define dprintf printf
21 // will not work for odd lengths
22 u16
ip_csum(u8
*src
, int len
)
27 for (i
=0; i
<len
; i
+=2)
28 csum
+= (src
[i
]<<8) + src
[i
+1];
30 csum
= (csum
&0xffff)+(csum
>>16);
31 csum
= (csum
&0xffff)+(csum
>>16); /* in some cases it overflows again */
35 const static u8 ip_template
[] = { 0x45, 0, 0,0, 0,0, 0,0, 0x20 };
38 * netpacket_prepare_ip
39 * Can fail if IP is not yet known. In this case it sends an arp request.
40 * Then fails. User should resubmit the packet in a second or so.
42 int netpacket_prepare_ip(struct netpacket
*packet
, const ip_t dest
, u16 payload_len
)
44 struct ip_packet
*ip
= &packet
->ip
;
45 struct ethernet_frame
*ethernet
= &packet
->ethernet
;
47 memcpy(packet
->ip
.raw
, ip_template
, sizeof(ip_template
));
48 ip
->protocol
= IP_PROT_UDP
;
49 put_be16(ip
->len
, payload_len
+ sizeof(struct ip_packet
));
50 ip
->hcsum
[0] = ip
->hcsum
[1] = 0;
51 memcpy(ip
->src
, netconfig
.ip
, sizeof(ip_t
));
52 memcpy(ip
->dest
, dest
, sizeof(ip_t
));
54 u16 csum
= ip_csum(packet
->ip
.raw
, 20);
55 ip
->hcsum
[0] = csum
>>8;
58 memcpy(ethernet
->src
, netconfig
.mac
, sizeof(mac_t
));
59 if (arp_ip2mac(ethernet
->dest
, dest
) < 0) {
60 netpacket_alloc_discard();
61 int ret
= arp_request(dest
);
62 /* now we must fail the current packet, since we can't send before getting arp reply */
63 printf("%s: mac not cached, arp request: %d\n", __func__
, ret
);
67 put_be16(ethernet
->type
, ETHERTYPE_IP
);
71 int netpacket_prepare_udp(struct netpacket
*packet
, const ip_t dest
, u16 sport
, u16 dport
, u16 payload_len
)
75 ret
= netpacket_prepare_ip(packet
, dest
, payload_len
+sizeof(struct udp_packet
));
79 put_be16(packet
->udp
.sport
, sport
);
80 put_be16(packet
->udp
.dport
, dport
);
81 put_be16(packet
->udp
.len
, payload_len
+sizeof(struct udp_packet
));
82 put_be16(packet
->udp
.checksum
, 0); /* it is optional */
87 static struct netpacket
*netpacket_alloc_udp(int payloadlen
)
89 return netpacket_alloc(offsetof(struct netpacket
, udp
) + sizeof(struct udp_packet
) + payloadlen
);
92 int netpacket_alloc_and_prepare_udp(struct netpacket
**_packet
, const ip_t dest
, u16 sport
, u16 dport
, u16 len
)
94 struct netpacket
*packet
= netpacket_alloc_udp(len
);
97 if (netpacket_prepare_udp(packet
, dest
, sport
, dport
, len
) < 0) {
98 /* no need to deallocate, since we haven't called commit yet */
106 static u8 netpacket_buf_data
[1024];
107 static struct bip_buf netpacket_buf
;
108 static int netpacket_in_alloc
; // XXX consider just having a spinlock - code shouldn't block anyway
109 struct netpacket
*netpacket_alloc(unsigned len
)
111 if (netpacket_in_alloc
) {
112 dprintf("%s(%d): in alloc!\n", __func__
, len
);
116 if (!netpacket_buf
.data
) // XXX i don't like this
117 bip_buf_init(&netpacket_buf
, netpacket_buf_data
, sizeof(netpacket_buf_data
));
119 struct netpacket
*packet
= bip_buf_alloc(&netpacket_buf
, len
);
120 dprintf("%s(%d): %p\n", __func__
, len
, packet
);
123 netpacket_in_alloc
= 1;
128 void netpacket_alloc_discard(void)
130 dprintf("%s\n", __func__
);
131 netpacket_in_alloc
= 0;
134 int netpacket_send(struct netpacket
*packet
)
137 netpacket_print(packet
);
138 bip_buf_alloc_commit(&netpacket_buf
, packet
->len
);
139 dprintf("%s(%d)\n", __func__
, packet
->len
);
140 netpacket_in_alloc
= 0;
144 struct netpacket
* netpacket_getdata(void)
146 return bip_buf_getdata(&netpacket_buf
);
149 void netpacket_free(struct netpacket
*packet
)
151 bip_buf_free(&netpacket_buf
, packet
->len
);
152 dprintf("%s(%d)\n", __func__
, packet
->len
);
155 void netpacket_print(struct netpacket
*packet
)
157 u16 type
= get_be16(packet
->ethernet
.type
);
159 printf("ethernet: type:%x ", type
);
160 if (type
== ETHERTYPE_ARP
) {
161 printf("ARP %d", packet
->arp
.oper
[1]);
162 } else if (type
== ETHERTYPE_IP
) {
163 u8
*ip
= &packet
->ip
.src
[0];
165 printf("%d.%d.%d.%d ", ip
[0], ip
[1], ip
[2], ip
[3]);
166 ip
= &packet
->ip
.dest
[0];
167 printf("%d.%d.%d.%d ", ip
[0], ip
[1], ip
[2], ip
[3]);
169 int prot
= packet
->ip
.protocol
;
170 printf("protocol: %d ", prot
);
171 if (prot
== IP_PROT_UDP
) {
172 printf("UDP %d %d", get_be16(packet
->udp
.sport
), get_be16(packet
->udp
.dport
));
176 #ifdef DEBUG_NETPACKET
178 for (i
=0; i
<len
; i
++) {
179 if (i
== 14 || i
== 14+20)
181 printf(" %02x", packet
->ethernet
.raw
[i
]);