📄 dhcp_client.c
字号:
* and updating header, then send each fragment (in order).
*/
m = m0;
m_adj(m, hlen + firstlen - (u_short)ip->ip_len);
m->m_pkthdr.len = hlen + firstlen;
ip->ip_len = htons((u_short)m->m_pkthdr.len);
ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
ip->ip_sum = 0;
ip->ip_sum = in_cksum(m, hlen);
sendorfree:
for (m = m0; m; m = m0) {
m0 = m->m_nextpkt;
m->m_nextpkt = 0;
if (error == 0)
error = (*ifp->if_output)(ifp, m,
(struct sockaddr *)dst, ro->ro_rt);
else
m_freem(m);
}
if (error == 0) {
ipstat.ips_fragmented++;
}
}
done:
if (ro->ro_rt) {
RTFREE(ro->ro_rt);
}
return (error);
bad:
m_freem(m0);
goto done;
}
/* udp output func */
int
bsd_udp_output(struct mbuf *m, struct sockaddr_in *addrTo, unsigned char tos)
{
struct udpiphdr *ui;
struct in_addr laddr;
int len;
int s, error;
error = 0;
len = m->m_pkthdr.len;
s = splnet();
/*
* Calculate data length and get a mbuf
* for UDP and IP headers.
*/
M_PREPEND(m, sizeof(struct udpiphdr), M_DONTWAIT);
if (m == 0) {
error = ENOBUFS;
goto release;
}
/*
* Fill in mbuf with extended UDP header
* and addresses and length put into network format.
*/
ui = mtod(m, struct udpiphdr *);
ui->ui_next = ui->ui_prev = 0;
ui->ui_x1 = 0;
ui->ui_pr = IPPROTO_UDP;
ui->ui_len = htons((u_short)len + sizeof (struct udphdr));
//ui->ui_src.s_addr = htonl(gSysIpAddress.s_addr);
//ui->ui_sport = addrTo->sin_port; /* GTPU/DSCH/DCH/IPC src port just same as dst port */
ui->ui_src.s_addr = htonl(gstAddrFrom.sin_addr.s_addr);
ui->ui_sport = gstAddrFrom.sin_port;
ui->ui_dst.s_addr = addrTo->sin_addr.s_addr;
ui->ui_dport = addrTo->sin_port;
ui->ui_ulen = ui->ui_len;
/*
* Stuff checksum and output datagram.
*/
ui->ui_sum = 0;
((struct ip *)ui)->ip_len = sizeof (struct udpiphdr) + len;
((struct ip *)ui)->ip_ttl = 128; /* XXX */
((struct ip *)ui)->ip_tos = tos; /* XXX */
error = bsd_ip_output(m);
splx(s);
return (error);
release:
m_freem(m);
splx(s);
return (error);
}
/* udp send to calling bsd_udp_output/bsd_ip_output and set TOS and allocate mbuf if needed ,
NOTE: SDU released here automatically regardless of success or failure including mbuf if allocated
NOTE: please modify gstAddrTo and gstAddrFrom used by bsd_udp_out()
*/
int
Comm_UdpDataReq(unsigned char *pBuf, unsigned int dataLen, struct sockaddr_in *addrTo, unsigned char tos)
{
struct mbuf *ptrMbuf = NULL;
unsigned char *bufp = NULL;
ptrMbuf = mBufClGet(M_DONTWAIT, MT_DATA, 2048, TRUE);
if (ptrMbuf == NULL) {
gSysUdpStat.sysUdpOutputFailed++;
return ERROR;
}
bcopy(pBuf, ptrMbuf->m_data, dataLen);
if (ptrMbuf == NULL) {
gSysUdpStat.sysUdpOutputFailed++;
return ERROR;
}
ptrMbuf->m_len = dataLen;
ptrMbuf->m_pkthdr.rcvif = NULL;
ptrMbuf->m_pkthdr.len = dataLen;
ptrMbuf->m_flags |= M_PKTHDR;
if (bsd_udp_output(ptrMbuf, addrTo, tos)) {
gSysUdpStat.sysUdpOutputFailed++;
return ERROR;
}
gSysUdpStat.sysUdpOutput++;
return 0;
}
int dhcp_client_tx_data_req
(
unsigned char *pBuf,
unsigned int dataLen,
unsigned int srcIp,
unsigned int dstIp,
unsigned short srcPort,
unsigned short dstPort
)
{
gstAddrTo.sin_len = sizeof(struct sockaddr_in);
gstAddrTo.sin_family = AF_INET;
gstAddrTo.sin_port = htons(dstPort);
gstAddrTo.sin_addr.s_addr = htonl(dstIp);
gstAddrFrom.sin_len = sizeof(struct sockaddr_in);
gstAddrFrom.sin_family = AF_INET;
gstAddrFrom.sin_port = htons(srcPort);
gstAddrFrom.sin_addr.s_addr = htonl(srcIp);
TRACE0("tx to dstIp 0x%x dstPort %d srcIp 0x%x srcPort %d dataLen %d\n",dstIp,dstPort,srcIp,srcPort,dataLen);
DUMP0(pBuf,dataLen);
if (ERROR == Comm_UdpDataReq(pBuf,dataLen,&gstAddrTo,0)) {
TRACE3("call Comm_UdpDataReq failed\n");
return ERROR;
}
return OK;
}
/*******************************************************************************
*
* pickup_opt - extract an option from a DHCP message
*
* This routine searches the fields in a DHCP message for the option specified
* by the <tag> parameter. If the file and sname message fields are overloaded
* with options, they are searched as well. The search order is:
*
* options field -> 'file' field -> 'sname' field
*
* RETURNS: Pointer to first occurrence of option, or NULL if not found.
*
* ERRNO: N/A
*
* SEE ALSO: RFC 1533
*
* NOMANUAL
*/
char * pickup_opt
(
struct dhcp * msg, /* Incoming message copied to structure */
int msglen, /* Length of message */
char tag /* RFC 1533 tag for desired option */
)
{
BOOL sname_is_opt = FALSE;
BOOL file_is_opt = FALSE;
int i = 0;
char * opt = NULL;
char * found = NULL;
/* search option field. */
opt = &msg->options[MAGIC_LEN];
for (i = 0; i < msglen - DFLTDHCPLEN + DFLTOPTLEN - MAGIC_LEN; i++)
{
if (*(opt + i) == tag)
{
found = (opt + i);
break;
}
else if (*(opt + i) == _DHCP_END_TAG)
break;
else if (*(opt + i) == _DHCP_OPT_OVERLOAD_TAG)
{
i += 2 ;
if (*(opt + i) == 1)
file_is_opt = TRUE;
else if (*(opt + i) == 2)
sname_is_opt = TRUE;
else if (*(opt + i) == 3)
file_is_opt = sname_is_opt = TRUE;
continue;
}
else if (*(opt + i) == _DHCP_PAD_TAG)
continue;
else
i += *(u_char *)(opt + i + 1) + 1;
}
if (found != NULL)
return (found);
/* If necessary, search file field. */
if (file_is_opt)
{
opt = msg->file;
for (i = 0; i < sizeof (msg->file); i++)
{
if (*(opt + i) == _DHCP_PAD_TAG)
continue;
else if (*(opt + i) == _DHCP_END_TAG)
break;
else if (*(opt + i) == tag)
{
found = (opt + i);
break;
}
else
i += *(u_char *)(opt + i + 1) + 1;
}
if (found != NULL)
return (found);
}
/* If necessary, search sname field. */
if (sname_is_opt)
{
opt = msg->sname;
for (i = 0; i < sizeof (msg->sname); i++)
{
if (*(opt + i) == _DHCP_PAD_TAG)
continue;
else if (*(opt + i) == _DHCP_END_TAG)
break;
else if (*(opt + i) == tag)
{
found = (opt + i);
break;
}
else
i += *(u_char *)(opt + i + 1) + 1;
}
if (found != NULL)
return(found);
}
return(NULL);
}
/*******************************************************************************
*
* get_cid - Retrieve client identifier
*
* This routine extracts the client identifier from the options field of the
* DHCP client request and stores the <type>:<value> pair in the given
* structure. If no explicit client ID is given, the routine uses the hardware
* address, as specified by RFC 1541.
*
* RETURNS: N/A
*
* ERRNO: N/A
*
* NOMANUAL
*/
int get_cid
(
struct dhcp *msg, /* pointer to incoming message */
int length, /* length of incoming message */
struct client_id *cid /* pointer to storage for parsed data */
)
{
char *option = NULL;
option = pickup_opt (msg, length, _DHCP_CLIENT_ID_TAG);
if (option != NULL)
{
/*
Code Len Type Client-Identifier
+-----+-----+-----+-----+-----+---
| 61 | n | t1 | i1 | i2 | ...
+-----+-----+-----+-----+-----+---
*/
cid->idlen = ( (int)DHCPOPTLEN (option)) - 1; /* -1 for ID type */
bcopy (OPTBODY (option) + 1, cid->id, cid->idlen);
cid->idtype = *OPTBODY (option);
return OK;
}
else
{
return ERROR;
/* haddr is used to substitute for client identifier */
cid->idlen = msg->hlen;
cid->idtype = msg->htype;
bcopy (msg->chaddr, cid->id, msg->hlen);
}
return OK;
}
void dump_cid(struct client_id *pCid)
{
if(pCid) {
TRACE("cid type %d cid len %d cid subnet 0x%x\n",pCid->idtype,pCid->idlen,
(unsigned int)pCid->subnet.s_addr);
DUMP(pCid->id,pCid->idlen);
}
return ;
}
void dump_haddr(struct chaddr *pHaddr)
{
if(pHaddr) {
TRACE("haddr type %d haddr len %d\n",pHaddr->htype,pHaddr->hlen);
DUMP(pHaddr->haddr,pHaddr->hlen);
}
return ;
}
void dump_cid_haddr(struct client_id *pCid,struct chaddr *pHaddr)
{
if(pCid) {
TRACE("cid type %d cid len %d cid subnet 0x%x\n",pCid->idtype,pCid->idlen,
(unsigned int)pCid->subnet.s_addr);
DUMP(pCid->id,pCid->idlen);
} else if(pHaddr) {
TRACE("haddr type %d haddr len %d\n",pHaddr->htype,pHaddr->hlen);
DUMP(pHaddr->haddr,pHaddr->hlen);
}
return ;
}
void dump_ip(struct in_addr *pIp)
{
unsigned char *pByte = NULL;
if(pIp) {
pByte = (unsigned char *)pIp;
TRACE("ip 0x%8x(%d.%d.%d.%d)\n",(unsigned int)pIp->s_addr,pByte[0],pByte[1],pByte[2],pByte[3]);
}
}
/*******************************************************************************
*
* get_haddr - Retrieve hardware address
*
* This routine extracts the hardware address
*
* RETURNS: N/A
*
* ERRNO: N/A
*
* NOMANUAL
*/
int get_haddr
(
struct dhcp *msg, /* pointer to incoming message */
struct chaddr *haddr /* pointer to storage for parsed data */
)
{
/* haddr is used to substitute for client identifier */
haddr->hlen = msg->hlen;
haddr->htype = msg->htype;
bcopy (msg->chaddr, haddr->haddr, msg->hlen);
return OK;
}
/*******************************************************************************
*
* checksum - portable internet checksum calculation routine
*
* This checksums the buffer <pAddr> of length <len>. This routine differs
* from the standard checksum algorithm (in_cksum) in that it checksums a buffer
* while the other checksums an mbuf chain. For of a description of the
* internet checksum algorithm, please refer to RFC 1071.
*
* RETURNS: checksum
*
* NOMANUAL
*/
u_short dhcp_checksum
(
u_short * pAddr, /* pointer to buffer */
int len /* length of buffer */
)
{
int nLeft = len;
int sum = 0;
u_short * w = pAddr;
u_short answer;
while (nLeft > 1)
{
sum += *w++;
nLeft -= 2;
}
if (nLeft == 1)
#if _BYTE_ORDER == _BIG_ENDIAN
sum += 0 | ((*(u_char *) w) << 8);
#else
sum += *(u_char *) w;
#endif
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = sum;
return (~answer & 0xffff);
}
/*******************************************************************************
*
* dhcp_time - return system uptime
*
* This routine is similar to the POSIX time() routine, except it returns
* the time in terms of the number of seconds that the system has been
* running and is immune to changes in the system clock made by
* clock_settime(). Note however that it is _not_ immune to someone
* calling tickSet(). This is not the same thing as changing the
* calendar time though and should happen less frequently.
*
* RETURNS: Number of seconds since the system was booted.
*
* ERRNO: N/A
*
* NOMANUAL
*/
time_t dhcp_time
(
time_t *timer
)
{
ULONG sysTicks;
sysTicks = tickGet()/sysClkRateGet();
if (timer != NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -