关于inet_addr()函数陷阱

本文通过一个C语言网络编程示例揭示了一个常见错误:使用inet_addr函数获取IP地址时返回的静态内存指针可能会被后续操作覆盖。文章详细介绍了如何初始化和打印结构体中的IP地址,并解释了inet_addr函数的行为及其潜在问题。
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <net/if.h>

struct tokenID
{
    struct in_addr subnet_addr;
    struct in_addr outnet_addr;
    unsigned short outnet_port;
};

int main()
{
    tokenID peer;
    memset(&peer, 0, sizeof(peer));

    peer.outnet_addr.s_addr = inet_addr("187.49.86.238");
    peer.subnet_addr.s_addr = inet_addr("192.168.20.8");

    char *p1, *p2;

    p1 = inet_ntoa(peer.outnet_addr);
    p2 = inet_ntoa(peer.subnet_addr);
    printf("p1 =%s, p2 = %s\n",p1, p2);

    return 0;

}

返回值:p1 =192.168.20.8, p2 = 192.168.20.8

原因:inet_addr函数的返回了static内存的指针,导致前面的值被后面的覆盖了


问题延伸:
1.printf函数执行参数计算顺序是从右往左的
2.返回static内部变量的函数

# 你是一名linux网络工程师,熟悉IPv6协议和linux内核 # 参考代码 int ip6_datagram_send_ctl(struct net *net, struct sock *sk, struct msghdr *msg, struct flowi6 *fl6, struct ipcm6_cookie *ipc6) { struct in6_pktinfo *src_info; struct cmsghdr *cmsg; struct ipv6_rt_hdr *rthdr; struct ipv6_opt_hdr *hdr; struct ipv6_txoptions *opt = ipc6->opt; int len; int err = 0; for_each_cmsghdr(cmsg, msg) { int addr_type; if (!CMSG_OK(msg, cmsg)) { err = -EINVAL; goto exit_f; } if (cmsg->cmsg_level == SOL_SOCKET) { err = __sock_cmsg_send(sk, msg, cmsg, &ipc6->sockc); if (err) return err; continue; } if (cmsg->cmsg_level != SOL_IPV6) continue; switch (cmsg->cmsg_type) { case IPV6_PKTINFO: case IPV6_2292PKTINFO: { struct net_device *dev = NULL; int src_idx; if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) { err = -EINVAL; goto exit_f; } src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); src_idx = src_info->ipi6_ifindex; if (src_idx) { if (fl6->flowi6_oif && src_idx != fl6->flowi6_oif && (READ_ONCE(sk->sk_bound_dev_if) != fl6->flowi6_oif || !sk_dev_equal_l3scope(sk, src_idx))) return -EINVAL; fl6->flowi6_oif = src_idx; } addr_type = __ipv6_addr_type(&src_info->ipi6_addr); rcu_read_lock(); if (fl6->flowi6_oif) { dev = dev_get_by_index_rcu(net, fl6->flowi6_oif); if (!dev) { rcu_read_unlock(); return -ENODEV; } } else if (addr_type & IPV6_ADDR_LINKLOCAL) { rcu_read_unlock(); return -EINVAL; } if (addr_type != IPV6_ADDR_ANY) { int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; if (!ipv6_can_nonlocal_bind(net, inet_sk(sk)) && !ipv6_chk_addr_and_flags(net, &src_info->ipi6_addr, dev, !strict, 0, IFA_F_TENTATIVE) && !ipv6_chk_acast_addr_src(net, dev, &src_info->ipi6_addr)) err = -EINVAL; else fl6->saddr = src_info->ipi6_addr; } ... } # 问题描述 分析上述ip6_datagram_send_ctl校验失败返回err = -EINVAL判断逻辑失败原因,给出用户态radvd进程合理解决建议
06-11
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值