⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dhcp_client.c

📁 wimax bs模拟器
💻 C
📖 第 1 页 / 共 5 页
字号:
		 * 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 + -