first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
+224
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Computer, Inc.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <sys.h>
|
||||
#include <sys/task.h>
|
||||
#include <lib/net.h>
|
||||
#include <lib/net/ethernet.h>
|
||||
#include <lib/net/ipv4.h>
|
||||
#include <lib/net/arp.h>
|
||||
#include <lib/net/xp.h>
|
||||
|
||||
arp_cache_t arpcache;
|
||||
|
||||
static int arp_transmit(bool reply,char* tomacaddr,uint32_t toip)
|
||||
{
|
||||
//generate packet and send it down to the ethernet layer
|
||||
mymbuf_t *packet;
|
||||
char *data;
|
||||
char dstmac[] = {0xff,0xff,0xff,0xff,0xff,0xff};
|
||||
uint32_t srcip;
|
||||
|
||||
|
||||
packet = mbuf_initialize(28,14,4); //28byte arp, 14 ethernet, 4 ethernet trailer
|
||||
data = mbuf_tail(packet,28);
|
||||
*(uint16_t *)&data[ARP_OFFSET_HTYPE] = htons(1); //ethernet
|
||||
*(uint16_t *)&data[ARP_OFFSET_PTYPE] = htons(0x0800); //ipv4
|
||||
data[ARP_OFFSET_HLEN] = 6; //macaddr is 6 bytes
|
||||
data[ARP_OFFSET_PLEN] = 4; //ip is 4 bytes
|
||||
*(uint16_t *)&data[ARP_OFFSET_OPER] = htons(reply ? 2 : 1);
|
||||
|
||||
xp_getmac((uint8_t*)&data[ARP_OFFSET_SHA]);
|
||||
|
||||
srcip = ipv4_get_ip();
|
||||
*(uint32_t *)&data[ARP_OFFSET_SHA+6] = htonl(srcip);
|
||||
|
||||
if(tomacaddr == 0) {
|
||||
memcpy(&data[ARP_OFFSET_SHA+10],"\0\0\0\0\0\0",6);
|
||||
} else {
|
||||
memcpy(&data[ARP_OFFSET_SHA+10],tomacaddr,6);
|
||||
}
|
||||
toip = htonl(toip);
|
||||
memcpy(&data[ARP_OFFSET_SHA+16],&toip,4);
|
||||
|
||||
add_eth_and_transmit(packet,dstmac,ETHERTYPE_ARP);
|
||||
mbuf_destroy(packet);
|
||||
return 0;
|
||||
}
|
||||
int arp_hash(uint32_t ip)
|
||||
{
|
||||
return ip % ARP_CACHE_SIZE;
|
||||
}
|
||||
|
||||
int arp_cache_add(uint32_t ip, const char *mac)
|
||||
{
|
||||
arp_cache_entry_t *ce = &arpcache.cache[arp_hash(ip)];
|
||||
if (ce->ip == 0 || ce->ip == ip)
|
||||
goto update;
|
||||
while (ce->next) {
|
||||
ce = ce->next;
|
||||
if(ce->ip == ip)
|
||||
goto update;
|
||||
}
|
||||
// Not in the list, add a new entry
|
||||
ce->next = malloc(sizeof(arp_cache_entry_t));
|
||||
ce = ce->next;
|
||||
ce->next = 0;
|
||||
update:
|
||||
ce->ip = ip;
|
||||
memcpy(ce->mac,mac,6);
|
||||
// printf("arp: learned %#I at %M\n", &ce->ip, &ce->mac);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arp_cache_get(uint32_t ip,char *mac)
|
||||
{
|
||||
arp_cache_entry_t *ce = &arpcache.cache[arp_hash(ip)];
|
||||
|
||||
if(ip == ce->ip)
|
||||
goto found;
|
||||
while(ce->next) {
|
||||
ce = ce->next;
|
||||
if(ip == ce->ip)
|
||||
goto found;
|
||||
}
|
||||
return -1;
|
||||
found:
|
||||
// printf("arp: found %#I at %M\n", &ce->ip, &ce->mac);
|
||||
if (mac)
|
||||
memcpy(mac,ce->mac,6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arp_cache_delete(void)
|
||||
{
|
||||
arp_cache_entry_t *ce;
|
||||
int i;
|
||||
|
||||
for(i=0;i<ARP_CACHE_SIZE;i++) {
|
||||
ce = arpcache.cache[i].next;
|
||||
while(ce) {
|
||||
arp_cache_entry_t *next;
|
||||
next = ce->next;
|
||||
free(ce);
|
||||
ce = next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void arp_dump_table(void)
|
||||
{
|
||||
arp_cache_entry_t *ce;
|
||||
int i;
|
||||
|
||||
for(i=0;i<ARP_CACHE_SIZE;i++) {
|
||||
ce = &arpcache.cache[i];
|
||||
while (ce) {
|
||||
if (ce->ip != 0)
|
||||
printf("ip: %#I\tmac: %M\n", &ce->ip, &ce->mac);
|
||||
ce = ce->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int arp_get_macaddr(uint32_t ip, char *outmac)
|
||||
{
|
||||
if(arp_cache_get(ip,outmac) < 0) {
|
||||
// printf("Sending request for 0x%x\n",ip);
|
||||
arp_transmit(false,0,ip);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* send arp requests until it is satisfied or timeout */
|
||||
int arp_fill(uint32_t ip, utime_t timeout)
|
||||
{
|
||||
utime_t t;
|
||||
|
||||
t = system_time();
|
||||
do {
|
||||
if (arp_cache_get(ip, NULL) >= 0)
|
||||
return 0;
|
||||
|
||||
arp_transmit(false, 0, ip);
|
||||
task_sleep(100*1000);
|
||||
} while (system_time() - t < timeout);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int arp_workloop(char *packet,int offset,int len,void *prevlayerdata)
|
||||
{
|
||||
uint16_t htype,ptype;
|
||||
uint8_t hlen,plen;
|
||||
uint16_t oper;
|
||||
unsigned char *buffer = (unsigned char *)packet+offset;
|
||||
uint32_t itoip,ifromip;
|
||||
unsigned char *tmp;
|
||||
|
||||
htype = ntohs(*(uint16_t*)&buffer[ARP_OFFSET_HTYPE]);
|
||||
ptype = ntohs(*(uint16_t*)&buffer[ARP_OFFSET_PTYPE]);
|
||||
hlen = buffer[ARP_OFFSET_HLEN];
|
||||
plen = buffer[ARP_OFFSET_PLEN];
|
||||
oper = ntohs(*(uint16_t*)&buffer[ARP_OFFSET_OPER]);
|
||||
|
||||
// printf("arp: 0x%x 0x%x %d %d op %d\n", htype, ptype, hlen, plen, oper);
|
||||
|
||||
if ((htype != 1) || /* ethernet */
|
||||
(ptype != 0x800) || /* IPv4 */
|
||||
(hlen != 6) || /* 6-byte MAC */
|
||||
(plen != 4)) { /* 4-byte protocol address */
|
||||
// printf("Not ethernet. Bailing\n");
|
||||
return -1;
|
||||
}
|
||||
tmp = &buffer[ARP_OFFSET_SHA+hlen];
|
||||
ifromip = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
|
||||
|
||||
tmp = &buffer[ARP_OFFSET_SHA+(2*hlen)+plen];
|
||||
itoip = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3];
|
||||
|
||||
// printf("arp: from %#I to %#I\n", &ifromip, &itoip);
|
||||
|
||||
//someone sent out their address
|
||||
arp_cache_add(ifromip,(char *)&buffer[ARP_OFFSET_SHA]);
|
||||
|
||||
if (oper == 1) {
|
||||
if (itoip == ipv4_get_ip()) {
|
||||
// printf("arp: sending reply to %#I\n", &ifromip);
|
||||
arp_transmit(true,(char *)&buffer[ARP_OFFSET_SHA],ifromip);
|
||||
} else {
|
||||
// printf("arp: dest %I not us\n", &itoip);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int arp_layer(bool on)
|
||||
{
|
||||
static int id = -1;
|
||||
if(on) {
|
||||
if(id == -1) {
|
||||
memset(&arpcache,0,sizeof(arpcache));
|
||||
id = registerEtherTypeHandler(ETHERTYPE_ARP,arp_workloop);
|
||||
}
|
||||
} else {
|
||||
if(id >= 0) {
|
||||
unregisterEtherTypeHandler(id);
|
||||
arp_cache_delete();
|
||||
id = -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Computer, Inc.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <lib/net/callbacks.h>
|
||||
|
||||
int registerCallback(callbacks_t *cbs,int port,callback_handler cb)
|
||||
{
|
||||
listentry_t *cur = cbs->first;
|
||||
int i = 1;
|
||||
|
||||
while(cur && cur->next) {
|
||||
cur = cur->next;
|
||||
i++;
|
||||
}
|
||||
if(!cur) { //no elems
|
||||
cur = cbs->first = malloc(sizeof(listentry_t));
|
||||
i = 0; //first.
|
||||
} else {
|
||||
cur->next = malloc(sizeof(listentry_t));
|
||||
cur = cur->next;
|
||||
}
|
||||
cur->next = 0;
|
||||
cur->callback = cb;
|
||||
cur->port = port;
|
||||
cur->cb_id = i;
|
||||
return cur->cb_id;
|
||||
}
|
||||
int unregisterCallback(callbacks_t *cbs,int cb_id)
|
||||
{
|
||||
listentry_t *cur = cbs->first;
|
||||
listentry_t *prev = 0;
|
||||
|
||||
while(cur) {
|
||||
if(cur->cb_id == cb_id) {
|
||||
if(prev == 0) {
|
||||
cbs->first = cur->next;
|
||||
} else {
|
||||
prev->next = cur->next;
|
||||
}
|
||||
free(cur);
|
||||
return 0;
|
||||
}
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
callback_handler find_callback(callbacks_t *cbs,int port)
|
||||
{
|
||||
listentry_t *cur = cbs->first;
|
||||
|
||||
while(cur) {
|
||||
if(cur->port == port) {
|
||||
return cur->callback;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Computer, Inc.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <drivers/ethernet.h>
|
||||
#include <lib/macho.h>
|
||||
#include <lib/net.h>
|
||||
#include <lib/net/arp.h>
|
||||
#include <sys/menu.h>
|
||||
|
||||
#if defined(WITH_MENU) && WITH_MENU
|
||||
|
||||
int do_net(int argc, struct cmd_arg *args)
|
||||
{
|
||||
if (argc < 2) {
|
||||
puts("not enough arguments.\n");
|
||||
usage:
|
||||
printf("%s init\n", args[0].str);
|
||||
printf("%s arp\n", args[0].str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strcmp("init", args[1].str) == 0) {
|
||||
start_network_stack();
|
||||
} else if (strcmp("arp", args[1].str) == 0) {
|
||||
arp_dump_table();
|
||||
} else {
|
||||
puts("unrecognized command.\n");
|
||||
goto usage;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MENU_COMMAND_DEVELOPMENT(net, do_net, "network/ethernet stuff", NULL);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Computer, Inc.
|
||||
*/
|
||||
//a very minimal Ethernet stack.
|
||||
//protocol handlers can register for a certain service, and this layer will call their functions when a packet of that type arrive
|
||||
#include <debug.h>
|
||||
#include <stdint.h>
|
||||
#include <sys.h>
|
||||
#include <sys/callout.h>
|
||||
#include <lib/net/xp.h>
|
||||
#include <lib/net/callbacks.h>
|
||||
#include <lib/net/ethernet.h>
|
||||
|
||||
//For the different layers
|
||||
#include <lib/net/arp.h>
|
||||
#include <lib/net/ipv4.h>
|
||||
#include <lib/net/udp.h>
|
||||
#include <lib/net/icmp.h>
|
||||
|
||||
|
||||
static callbacks_t ethercb;
|
||||
|
||||
int registerEtherTypeHandler(int ethertype,callback_handler cb)
|
||||
{
|
||||
return registerCallback(ðercb,ethertype,cb);
|
||||
}
|
||||
|
||||
int unregisterEtherTypeHandler(int id)
|
||||
{
|
||||
return unregisterCallback(ðercb,id);
|
||||
}
|
||||
|
||||
|
||||
static int parseEtherHeader(char *buff,int len,uint16_t *ethertype)
|
||||
{
|
||||
|
||||
//XXX: Check that the destination macaddress matches.
|
||||
if(ethertype) {
|
||||
*ethertype = ntohs(*(uint16_t *)(buff+12));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ethernet_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
void ethernet_uninit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void ethernet_input(mymbuf_t *inputbuf)
|
||||
{
|
||||
uint16_t ethertype;
|
||||
int len;
|
||||
char *rawbuf;
|
||||
callback_handler cb;
|
||||
|
||||
len = mbuf_getlength(inputbuf);
|
||||
rawbuf = mbuf_getlinear(inputbuf);
|
||||
//This fails if the packet was not directed to us (ie, wrong macaddr)
|
||||
if(parseEtherHeader(rawbuf,len,ðertype) == 0) {
|
||||
cb = find_callback(ðercb,ethertype);
|
||||
if(cb) {
|
||||
cb(rawbuf,ETHERNET_OFFSET,len,0);
|
||||
} else {
|
||||
// printf("Unsupported ethertype 0x%x\n",ethertype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
//Called from timer (background) or from tsys commandprompt if not background
|
||||
//Handles maxpkt packages before returning. (Or until it would have to block)
|
||||
void ethernet_workloop(struct callout *c, void *param)
|
||||
{
|
||||
int i;
|
||||
uint16_t ethertype;
|
||||
int len;
|
||||
char *rawbuf;
|
||||
callback_handler cb;
|
||||
int maxpkt = (int)param;
|
||||
// utime_t now;
|
||||
//
|
||||
|
||||
callout_reset(c, 0);
|
||||
|
||||
if(!buf)
|
||||
return;
|
||||
|
||||
for(i = 0;i<maxpkt;i++) {
|
||||
// now = system_time();
|
||||
mbuf_setlength(buf,0);
|
||||
mbuf_setoffset(buf,0);
|
||||
if(xp_get_packet(buf)) {
|
||||
len = mbuf_getlength(buf);
|
||||
rawbuf = mbuf_getlinear(buf);
|
||||
//This fails if the packet was not directed to us (ie, wrong macaddr)
|
||||
if(parseEtherHeader(rawbuf,len,ðertype) == 0) {
|
||||
cb = find_callback(ðercb,ethertype);
|
||||
if(cb) {
|
||||
cb(rawbuf,ETHERNET_OFFSET,len,0);
|
||||
} else {
|
||||
// printf("Unsupported ethertype 0x%x\n",ethertype);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
// now = system_time() - now;
|
||||
// printf("a package took %ld usec\n",now);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
int add_eth_and_transmit(mymbuf_t *buffer,char *macaddrto,int ethertype)
|
||||
{
|
||||
char *ethernethead;
|
||||
// utime_t perftime = system_time();
|
||||
|
||||
ethernethead = mbuf_head(buffer,14);
|
||||
if(!ethernethead) {
|
||||
dprintf(DEBUG_INFO, "Ethernetheader: Not enough space in mbuf.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(ethernethead,macaddrto,6);
|
||||
xp_getmac((uint8_t*)ðernethead[6]);
|
||||
*(uint16_t *)ðernethead[12] = htons(ethertype);
|
||||
/*
|
||||
tailcrc = mbuf_tail(buffer,4);
|
||||
|
||||
//XXX: Calculate CRC
|
||||
printf("Calculate CRC!\n");
|
||||
*/ // Is done by our ethernet driver...
|
||||
return xp_transmit_packet(buffer);
|
||||
// printf("transmit took %ld usec\n", system_time() - perftime);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Computer, Inc.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <lib/net/ipv4.h>
|
||||
#include <lib/net/callbacks.h>
|
||||
#include <lib/net/icmp.h>
|
||||
#include <lib/net/xp.h>
|
||||
|
||||
static callbacks_t icmpcb;
|
||||
|
||||
static uint16_t icmp_checksum(uint16_t *data,int len)
|
||||
{
|
||||
uint32_t sum =0;
|
||||
uint16_t res;
|
||||
|
||||
for(int i=0;i<len;i++)
|
||||
sum += data[i];
|
||||
sum = (sum &0xffff) + (sum >> 16);
|
||||
res = ~sum;
|
||||
return res;
|
||||
}
|
||||
static int icmp_send_echo(uint32_t toip,uint16_t identifier, uint16_t sequence,char *extradata,int datalen)
|
||||
{
|
||||
mymbuf_t *packet;
|
||||
char *data;
|
||||
int ret;
|
||||
|
||||
packet = mbuf_initialize(8+datalen,14+20,0);
|
||||
data = mbuf_tail(packet,8+datalen);
|
||||
|
||||
data[0] = data[1] = 0; //type and code
|
||||
data[2] = data[3] = 0; //checksum, will be calculated later
|
||||
*(uint16_t *)&data[4] = htons(identifier);
|
||||
*(uint16_t *)&data[6] = htons(sequence);
|
||||
memcpy(&data[8],extradata,datalen);
|
||||
*(uint16_t *)&data[2] = icmp_checksum((uint16_t *)data,(8+datalen)>>1);
|
||||
|
||||
ret = transmit_and_add_ipv4(packet,toip,IPV4_ICMP);
|
||||
mbuf_destroy(packet);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int icmp_workloop(char *data, int offset, int len,void *srcip)
|
||||
{
|
||||
char *buffer = data+offset;
|
||||
uint8_t type;
|
||||
uint8_t code;
|
||||
uint16_t checksum;
|
||||
|
||||
type = buffer[0];
|
||||
code = buffer[1];
|
||||
checksum = ntohs(*(uint16_t *)&(buffer[2]));
|
||||
|
||||
switch(type) {
|
||||
case ICMP_ECHO:
|
||||
{
|
||||
uint16_t identifier = ntohs(*(uint16_t *)&(buffer[4]));
|
||||
uint16_t sequence = ntohs(*(uint16_t *)&(buffer[6]));
|
||||
char *echodata = buffer+8;
|
||||
|
||||
// printf("Echo %s: ident: 0x%x,sequence: 0x%d\n",(data == ICMP_ECHO) ? "echo" : "reply",identifier,sequence);
|
||||
icmp_send_echo((uint32_t)srcip,identifier,sequence,echodata,len-offset-8);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Unsupported ICMP(%d)\n",type);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int icmp_layer(bool on)
|
||||
{
|
||||
static int id = -1;
|
||||
if(on) {
|
||||
if(id == -1) {
|
||||
id = registerIPV4Handler(IPV4_ICMP,icmp_workloop);
|
||||
}
|
||||
} else {
|
||||
if(id >= 0) {
|
||||
unregisterIPV4Handler(id);
|
||||
id = -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//Just registers a ICMP handler.
|
||||
int registerICMPHandler(int messagetype,callback_handler cb)
|
||||
{
|
||||
return registerCallback(&icmpcb,messagetype,cb);
|
||||
}
|
||||
|
||||
int unregisterICMPHandler(int id)
|
||||
{
|
||||
return unregisterCallback(&icmpcb,id);
|
||||
}
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Computer, Inc.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <lib/net.h>
|
||||
#include <lib/net/xp.h>
|
||||
#include <lib/net/ethernet.h>
|
||||
#include <lib/net/callbacks.h>
|
||||
#include <lib/net/arp.h>
|
||||
#include <lib/net/ipv4.h>
|
||||
|
||||
static callbacks_t ipcb;
|
||||
static uint32_t sCurrentIP;
|
||||
|
||||
|
||||
static int calculate_ipv4_checksum(uint16_t *data, int len)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
uint16_t res;
|
||||
for(int i=0;i<len;i++) {
|
||||
sum += (data[i]);
|
||||
}
|
||||
sum = (sum &0xffff) + (sum >> 16);
|
||||
res = ~sum;
|
||||
return res;
|
||||
}
|
||||
int transmit_and_add_ipv4(mymbuf_t *mbuf,uint32_t dest,int protocol)
|
||||
{
|
||||
int datalen;
|
||||
uint16_t *header;
|
||||
char outmac[6];
|
||||
uint32_t source;
|
||||
|
||||
datalen = mbuf_getlength(mbuf);
|
||||
if(datalen > 1480) {
|
||||
dprintf(DEBUG_INFO, "ipv4: fragmented ip packages not supported\n");
|
||||
return -1;
|
||||
}
|
||||
header = (uint16_t *)mbuf_head(mbuf,20);
|
||||
if(!header) {
|
||||
dprintf(DEBUG_INFO, "ipv4: No room to prepend the ipv4 header\n");
|
||||
return -1;
|
||||
}
|
||||
header[0] = htons((0x4 << 12) | (5 << 8) );
|
||||
header[1] = htons(datalen+20);
|
||||
header[2] = htons(0xBEEF);
|
||||
header[3] = 0;
|
||||
header[4] = htons((0xff << 8) | ((protocol & 0xff )));
|
||||
header[5] = 0; //cksum
|
||||
|
||||
source = ipv4_get_ip();
|
||||
char *ip = (char*)&header[6];
|
||||
ip[0] = (source & 0xff000000) >> 24;
|
||||
ip[1] = (source & 0xff0000) >> 16;
|
||||
ip[2] = (source & 0xff00) >> 8;
|
||||
ip[3] = (source & 0xff);
|
||||
|
||||
ip = (char*)&header[8];
|
||||
ip[0] = (dest & 0xff000000) >> 24;
|
||||
ip[1] = (dest & 0xff0000) >> 16;
|
||||
ip[2] = (dest & 0xff00) >> 8;
|
||||
ip[3] = (dest & 0xff);
|
||||
|
||||
header[5] = (calculate_ipv4_checksum(header,10));
|
||||
if(arp_get_macaddr(dest,outmac) < 0) {
|
||||
dprintf(DEBUG_SPEW, "ipv4: No mac address available for 0x%x, dropping and requesting mac for that host.\n",dest);
|
||||
return -1;
|
||||
}
|
||||
add_eth_and_transmit(mbuf,outmac,ETHERTYPE_IPV4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ipv4_set_ip(uint32_t ip)
|
||||
{
|
||||
char ipstr[32];
|
||||
ip2str((uint8_t *)&ip, ipstr, 32);
|
||||
dprintf(DEBUG_INFO, "Setting ip to %s\n", ipstr);
|
||||
sCurrentIP = ip;
|
||||
}
|
||||
//Returns our ip in host order.
|
||||
uint32_t ipv4_get_ip()
|
||||
{
|
||||
return sCurrentIP;
|
||||
}
|
||||
|
||||
//Called by the ethernet layer when a IPV4 packet was received.
|
||||
static int ipv4_workloop(char *data,int offset, int len,void *unused)
|
||||
{
|
||||
int headerlen;
|
||||
int totallen;
|
||||
int ttl,flags,cksum,protocol;
|
||||
// char sourceip[16],destip[16];
|
||||
char *buf = data+offset;
|
||||
callback_handler cb;
|
||||
uint32_t srcip;
|
||||
// utime_t perftime = system_time();
|
||||
|
||||
if(((buf[0] & 0xf0)>>4) != 0x4) {
|
||||
printf("not ipv4 (0x%x)\n",buf[0]&0xf0);
|
||||
return -1;
|
||||
}
|
||||
headerlen = buf[0] & 0xf;
|
||||
totallen = ntohs(*(uint16_t*)&buf[2]);
|
||||
flags = buf[6] & 0x7;
|
||||
if(flags) {
|
||||
dprintf(DEBUG_SPEW, "ipv4: Fragmented/Packets with flags not supported (0x%x)\n",flags);
|
||||
return -1;
|
||||
}
|
||||
ttl = buf[8];
|
||||
protocol = buf[9];
|
||||
cksum = ntohs(*(uint16_t*)&buf[9]);
|
||||
// ipv42str(&buf[12],sourceip);
|
||||
// ipv42str(&buf[16],destip);
|
||||
// printf("IPV4 %s -> %s, protocol: %d( headerlen: %d, totallen: %d)\n",sourceip,destip,protocol,headerlen,totallen);
|
||||
cb = find_callback(&ipcb,protocol);
|
||||
if(!cb) {
|
||||
// dprintf(DEBUG_SPEW, "ipv4: Unsupported protocol(0x%x)\n",protocol);
|
||||
return -1;
|
||||
}
|
||||
srcip = buf[12] << 24 | buf[13] << 16 | buf[14] << 8 | buf[15];
|
||||
cb(data,offset+(headerlen*sizeof(4)),len,(void*)srcip);
|
||||
// printf("ipv4 took %ld usec\n", system_time() - perftime);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ipv4_layer(bool on)
|
||||
{
|
||||
static int id = -1;
|
||||
if(on) {
|
||||
if(id == -1) {
|
||||
id = registerEtherTypeHandler(ETHERTYPE_IPV4,ipv4_workloop);
|
||||
}
|
||||
} else {
|
||||
if(id >= 0) {
|
||||
unregisterEtherTypeHandler(id);
|
||||
id = -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int registerIPV4Handler(int protocol,callback_handler handler)
|
||||
{
|
||||
return registerCallback(&ipcb,protocol,handler);
|
||||
}
|
||||
|
||||
int unregisterIPV4Handler(int id)
|
||||
{
|
||||
return unregisterCallback(&ipcb,id);
|
||||
}
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Computer, Inc.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <lib/heap.h>
|
||||
#include <lib/net/mbuf.h>
|
||||
|
||||
#ifndef CPU_CACHELINE_SIZE
|
||||
# define CPU_CACHELINE_SIZE 32
|
||||
#endif
|
||||
|
||||
mymbuf_t * mbuf_initialize(int packetsize,int header,int tail)
|
||||
{
|
||||
mymbuf_t *p = calloc(1, sizeof(mymbuf_t));
|
||||
|
||||
p->primarydata = memalign(packetsize + header+tail, CPU_CACHELINE_SIZE);
|
||||
p->offset = header;
|
||||
p->allocated_length = packetsize+header+tail;
|
||||
p->current_length = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
char *mbuf_head(mymbuf_t *buffer,int len)
|
||||
{
|
||||
// mbufentry_t **curr = &buffer->first;
|
||||
// mbufentry_t *last;
|
||||
|
||||
if(len <= buffer->offset && buffer->first == 0) {
|
||||
char *ret;
|
||||
//We have space in our buffer, let's just decrease offset and copy the data in
|
||||
ret = (buffer->primarydata + buffer->offset)-len;
|
||||
buffer->offset -= len;
|
||||
buffer->current_length += len;
|
||||
return ret;
|
||||
} else {
|
||||
printf("Request for %d bytes, only %d available\n",len,buffer->offset);
|
||||
/*
|
||||
while((*curr)->next) {
|
||||
curr = &(*curr)->next;
|
||||
}
|
||||
// first element
|
||||
if(*curr == 0) {
|
||||
buffer->first = malloc(sizeof(mbufentry_t));
|
||||
last = buffer->first;
|
||||
} else {
|
||||
last = (*curr)->next = malloc(sizeof(mbufentry_t));
|
||||
}
|
||||
last->len = len;
|
||||
last->data = malloc(len);
|
||||
last->flag = ENTRY_FLAG_ALLOCATED;
|
||||
last->next = 0;
|
||||
memcpy(last->data,indata,len);
|
||||
buffer->length += len;
|
||||
*/
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *mbuf_tail(mymbuf_t *buffer,int len)
|
||||
{
|
||||
if(buffer->offset+buffer->current_length+len <= buffer->allocated_length) {
|
||||
char *ret;
|
||||
ret = buffer->primarydata+buffer->offset + buffer->current_length;
|
||||
buffer->current_length += len;
|
||||
return ret;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int mbuf_copy(mymbuf_t *dest, const mymbuf_t *src)
|
||||
{
|
||||
if (dest->allocated_length < src->current_length)
|
||||
return -1;
|
||||
|
||||
dest->offset = 0;
|
||||
dest->current_length = src->current_length;
|
||||
memcpy(dest->primarydata, src->primarydata + src->offset, dest->current_length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mbuf_getlength(mymbuf_t *buffer)
|
||||
{
|
||||
return buffer->current_length;
|
||||
}
|
||||
int mbuf_getallocatedlength(mymbuf_t *buffer)
|
||||
{
|
||||
return buffer->allocated_length;
|
||||
}
|
||||
|
||||
void mbuf_setlength(mymbuf_t *buffer,int length)
|
||||
{
|
||||
buffer->current_length = length;
|
||||
}
|
||||
void mbuf_setoffset(mymbuf_t *buffer,int offset)
|
||||
{
|
||||
buffer->offset = offset;
|
||||
}
|
||||
|
||||
char *mbuf_getlinear(mymbuf_t *buf)
|
||||
{
|
||||
if(buf->first) {
|
||||
printf("getlinjear: not supported\n");
|
||||
return 0;
|
||||
}
|
||||
return buf->primarydata+buf->offset;
|
||||
|
||||
}
|
||||
void mbuf_destroy(mymbuf_t *buff)
|
||||
{
|
||||
if(buff->first) {
|
||||
printf("Not supported\n");
|
||||
return;
|
||||
}
|
||||
free(buff->primarydata);
|
||||
free(buff);
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Computer, Inc.
|
||||
*/
|
||||
#include <debug.h>
|
||||
#include <stdint.h>
|
||||
#include <drivers/ethernet.h>
|
||||
#include <lib/env.h>
|
||||
#include <lib/net.h>
|
||||
#include <lib/net/xp.h>
|
||||
#include <lib/net/callbacks.h>
|
||||
#include <lib/net/ethernet.h>
|
||||
|
||||
//For the different layers
|
||||
#include <lib/net/arp.h>
|
||||
#include <lib/net/ipv4.h>
|
||||
#include <lib/net/udp.h>
|
||||
#include <lib/net/icmp.h>
|
||||
|
||||
#include <sys/callout.h>
|
||||
|
||||
struct callout ethernet_cb;
|
||||
static bool netstack_initialized = false;
|
||||
|
||||
int start_network_stack(void)
|
||||
{
|
||||
if (netstack_initialized)
|
||||
return 0;
|
||||
|
||||
dprintf(DEBUG_INFO, "starting net stack\n");
|
||||
|
||||
/* get all of the environment variables we need up front */
|
||||
uint32_t ipaddr;
|
||||
uint8_t ethaddr[6];
|
||||
|
||||
if (env_get_ipaddr("ipaddr", &ipaddr) < 0) {
|
||||
printf("ipaddr environment variable not set or malformed, cannot start net stack\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (env_get_ethaddr("ethaddr", ethaddr)) {
|
||||
printf("ethaddr environment variable not set or malformed, cannot start net stack\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ethernet_init();
|
||||
xp_initialize();
|
||||
//YUCK! XXX: TODO:
|
||||
ipv4_layer(true);
|
||||
|
||||
ipv4_set_ip(htonl(ipaddr));
|
||||
arp_layer(true);
|
||||
icmp_layer(true);
|
||||
udp_layer(true);
|
||||
|
||||
#if WITH_HW_ETHERNET
|
||||
dprintf(DEBUG_INFO, "starting ethernet\n");
|
||||
ethstat_t *eth = eth_get_handle();
|
||||
|
||||
eth_setmacaddr(eth, (char *)ethaddr);
|
||||
eth_start(eth);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* start the ethernet work loop */
|
||||
callout_enqueue(ðernet_cb, 1000, ethernet_workloop, (void *)100);
|
||||
#endif
|
||||
|
||||
netstack_initialized = true;
|
||||
|
||||
/* gratuitous arp */
|
||||
char mac[6];
|
||||
arp_get_macaddr(ipv4_get_ip(), mac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stop_network_stack(void)
|
||||
{
|
||||
if (!netstack_initialized)
|
||||
return 0;
|
||||
|
||||
#if WITH_HW_ETHERNET
|
||||
ethstat_t *eth = eth_get_handle();
|
||||
|
||||
eth_stop(eth);
|
||||
#endif
|
||||
|
||||
ipv4_layer(false);
|
||||
arp_layer(false);
|
||||
icmp_layer(false);
|
||||
udp_layer(false);
|
||||
ethernet_uninit();
|
||||
netstack_initialized = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* utility routines for dealing with ip and mac address strings */
|
||||
void mac2str(uint8_t mac[6], char *ascii, size_t size)
|
||||
{
|
||||
snprintf(ascii, size, "%02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
|
||||
}
|
||||
|
||||
void ip2str(const uint8_t *ip, char *str, size_t size)
|
||||
{
|
||||
snprintf(str, size, "%u.%u.%u.%u", ip[3], ip[2], ip[1], ip[0]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
#
|
||||
# This document is the property of Apple Computer, Inc.
|
||||
# It is considered confidential and proprietary.
|
||||
#
|
||||
# This document may not be reproduced or transmitted in any form,
|
||||
# in whole or in part, without the express written permission of
|
||||
# Apple Computer, Inc.
|
||||
#
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
OPTIONS += \
|
||||
WITH_NET=1
|
||||
|
||||
ALL_OBJS += \
|
||||
$(LOCAL_DIR)/arp.o \
|
||||
$(LOCAL_DIR)/callbacks.o \
|
||||
$(LOCAL_DIR)/ethernet.o \
|
||||
$(LOCAL_DIR)/icmp.o \
|
||||
$(LOCAL_DIR)/ipv4.o \
|
||||
$(LOCAL_DIR)/mbuf.o \
|
||||
$(LOCAL_DIR)/net.o \
|
||||
$(LOCAL_DIR)/udp.o \
|
||||
$(LOCAL_DIR)/xp.o \
|
||||
$(LOCAL_DIR)/debug.o
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Computer, Inc.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <lib/net/callbacks.h>
|
||||
#include <lib/net/ipv4.h>
|
||||
#include <lib/net/xp.h>
|
||||
#include <lib/net/udp.h>
|
||||
|
||||
static callbacks_t udpcb;
|
||||
|
||||
static int udp_workloop(char *data, int offset,int len,void* srcip)
|
||||
{
|
||||
uint16_t sourceport,destport;
|
||||
uint16_t length,checksum;
|
||||
char *buffer = data+offset;
|
||||
callback_handler cb;
|
||||
udpinfo_t replyinfo;
|
||||
// utime_t perftime = system_time();
|
||||
|
||||
sourceport = ntohs(*(uint16_t *)&buffer[0]);
|
||||
destport = ntohs(*(uint16_t *)&buffer[2]);
|
||||
|
||||
length = ntohs(*(uint16_t *)&buffer[4]);
|
||||
checksum = ntohs(*(uint16_t *)&buffer[6]);
|
||||
|
||||
cb = find_callback(&udpcb,destport);
|
||||
if(!cb) {
|
||||
// printf("No listener on port %d\n");
|
||||
} else {
|
||||
replyinfo.srcip = (uint32_t)srcip;
|
||||
replyinfo.srcport = sourceport;
|
||||
replyinfo.length = length - 8;
|
||||
cb(data,offset+8,len,&replyinfo);
|
||||
}
|
||||
//printf("udp handler took %ld usec\n", system_time() - perftime);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int udp_layer(bool on)
|
||||
{
|
||||
static int id = -1;
|
||||
if(on) {
|
||||
if(id == -1) {
|
||||
id = registerIPV4Handler(IPV4_UDP,udp_workloop);
|
||||
}
|
||||
} else {
|
||||
if(id >= 0) {
|
||||
unregisterIPV4Handler(id);
|
||||
id = -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int transmit_udp(mymbuf_t *packet, uint32_t toip,int toport, int fromport)
|
||||
{
|
||||
uint16_t *udpbuf;
|
||||
int len;
|
||||
|
||||
udpbuf = (uint16_t *) mbuf_head(packet,8);
|
||||
len = mbuf_getlength(packet);
|
||||
if(!udpbuf) {
|
||||
printf("No room for udp package. bailing\n");
|
||||
return -1;
|
||||
}
|
||||
udpbuf[0] = htons(fromport);
|
||||
udpbuf[1] = htons(toport);
|
||||
udpbuf[2] = htons(len);
|
||||
//Checksum for UDP is ..crazy?
|
||||
//XXX: TODO: Checksum!
|
||||
udpbuf[3] = 0;
|
||||
return transmit_and_add_ipv4(packet,toip,IPV4_UDP);
|
||||
}
|
||||
int registerUDPHandler(int port,callback_handler cb)
|
||||
{
|
||||
return registerCallback(&udpcb,port,cb);
|
||||
}
|
||||
|
||||
int unregisterUDPHandler(int id)
|
||||
{
|
||||
return unregisterCallback(&udpcb,id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Computer, Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Computer, Inc.
|
||||
*/
|
||||
/* This file contains platform abstractions, implement the required functions for your platform */
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
#include <drivers/ethernet.h>
|
||||
#include <lib/net/xp.h>
|
||||
#include <lib/net/ethernet.h>
|
||||
|
||||
void *ethptr;
|
||||
|
||||
/* ethernet card is giving us info */
|
||||
void xp_packet_input(void *ethptr, mymbuf_t *inputbuf)
|
||||
{
|
||||
// printf("xp_packet_input: buf %p, len %d\n", inputbuf, mbuf_getlength(inputbuf));
|
||||
ethernet_input(inputbuf);
|
||||
}
|
||||
|
||||
#if 0
|
||||
mymbuf_t *xp_get_packet(mymbuf_t *inputbuf)
|
||||
{
|
||||
mymbuf_t *mb;
|
||||
char *buffer;
|
||||
int len = 1500;
|
||||
if(!inputbuf) {
|
||||
mb = mbuf_initialize(1500,0,0);
|
||||
} else {
|
||||
if(mbuf_getallocatedlength(inputbuf) < 1500) {
|
||||
return NULL;
|
||||
}
|
||||
mb = inputbuf;
|
||||
}
|
||||
buffer = mbuf_getlinear(mb);
|
||||
|
||||
if(eth_getpkt(ethptr,buffer,&len) < 0) {
|
||||
if(inputbuf != mb) {
|
||||
mbuf_destroy(mb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
mbuf_setlength(mb,len);
|
||||
return mb;
|
||||
}
|
||||
#endif
|
||||
|
||||
int xp_transmit_packet(mymbuf_t *buffer)
|
||||
{
|
||||
char *rawdata = mbuf_getlinear(buffer);
|
||||
|
||||
if(!rawdata) {
|
||||
printf("Handle linked mbuf's\n");
|
||||
return -1;
|
||||
}
|
||||
eth_output_packet(ethptr,rawdata,mbuf_getlength(buffer),0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xp_getmac(uint8_t *addr)
|
||||
{
|
||||
eth_getmacaddr(ethptr,(char *)addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xp_initialize(void)
|
||||
{
|
||||
ethptr = eth_get_handle();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user