Minix2.0/src/inet/generic/ip_lib.c
/*
ip_lib.c
*/
#include "inet.h"
#include "buf.h"
#include "type.h"
#include "assert.h"
#include "io.h"
#include "ip_int.h"
INIT_PANIC();
PUBLIC ipaddr_t ip_get_netmask (hostaddr)
ipaddr_t hostaddr;
{
ipaddr_t host, mask;
#if DEBUG & 256
{ where(); printf("ip_lib.c: ip_get_netmask(hostaddr= ");
writeIpAddr(hostaddr); printf(")\n"); }
#endif
host= ntohl(hostaddr);
if (!(host & 0x80000000L))
mask= 0xff000000L;
else if (!(host & 0x40000000L))
mask= 0xffff0000L;
else if (!(host & 0x20000000L))
mask= 0xffffff00L;
else
{
#if DEBUG
{ where(); printf("ip.c: marsian address: "); writeIpAddr (hostaddr);
printf("\n"); }
#endif
mask= 0xffffffffL;
}
return htonl(mask);
}
PUBLIC int ip_chk_hdropt (opt, optlen)
u8_t *opt;
int optlen;
{
int i, security_present= FALSE, lose_source_present= FALSE,
strict_source_present= FALSE, record_route_present= FALSE,
timestamp_present= FALSE;
#if DEBUG
{ where(); printf("ip_chk_hdropt(..., %d) called\n", optlen); }
#endif
assert (!(optlen & 3));
i= 0;
while (i<optlen)
{
#if DEBUG
{ where(); printf("*opt= %d\n", *opt); }
#endif
switch (*opt)
{
case 0x0: /* End of Option list */
return NW_OK;
case 0x1: /* No Operation */
i++;
opt++;
break;
case 0x82: /* Security */
if (security_present)
return EINVAL;
security_present= TRUE;
if (opt[1] != 11)
return EINVAL;
i += opt[1];
opt += opt[1];
break;
case 0x83: /* Lose Source and Record Route */
if (lose_source_present)
{
#if DEBUG
{ where(); printf("snd lose soruce route\n"); }
#endif
return EINVAL;
}
lose_source_present= TRUE;
if (opt[1]<3)
{
#if DEBUG
{ where(); printf("wrong length in source route\n"); }
#endif
return EINVAL;
}
i += opt[1];
opt += opt[1];
break;
case 0x89: /* Strict Source and Record Route */
if (strict_source_present)
return EINVAL;
strict_source_present= TRUE;
if (opt[1]<3)
return EINVAL;
i += opt[1];
opt += opt[1];
break;
case 0x7: /* Record Route */
if (record_route_present)
return EINVAL;
record_route_present= TRUE;
if (opt[1]<3)
return EINVAL;
i += opt[1];
opt += opt[1];
break;
case 0x88:
if (timestamp_present)
return EINVAL;
timestamp_present= TRUE;
if (opt[1] != 4)
return EINVAL;
switch (opt[3] & 0xff)
{
case 0:
case 1:
case 3:
break;
default:
return EINVAL;
}
i += opt[1];
opt += opt[1];
break;
default:
return EINVAL;
}
}
if (i > optlen)
{
#if DEBUG
{ where(); printf("option of wrong length\n"); }
#endif
return EINVAL;
}
return NW_OK;
}
void ip_print_frags(acc)
acc_t *acc;
{
ip_hdr_t *ip_hdr;
int first;
if (!acc)
printf("(null)");
for (first= 1; acc; acc= acc->acc_ext_link, first= 0)
{
assert (acc->acc_length >= IP_MIN_HDR_SIZE);
ip_hdr= (ip_hdr_t *)ptr2acc_data(acc);
if (first)
{
writeIpAddr(ip_hdr->ih_src);
printf(" > ");
writeIpAddr(ip_hdr->ih_dst);
}
printf(" {%x:%d@%d%c}", ip_hdr->ih_id,
ntohs(ip_hdr->ih_length),
(ntohs(ip_hdr->ih_flags_fragoff) & IH_FRAGOFF_MASK)*8,
(ntohs(ip_hdr->ih_flags_fragoff) & IH_MORE_FRAGS) ?
'+' : '\0');
}
}