如何在Uniflex系统中启用BSD套接字的广播功能?
修复Tektronix 4404(Uniflex系统)NRC套接字实现问题
背景
我正在修复一台1986年生产的Tektronix 4404设备,它运行Uniflex系统,其BSD套接字由Network Research Corporation(NRC)实现,但没有任何官方文档,仅有的头文件里也没有函数声明。
我需要找到net_ioctl()这类套接字控制函数的相关信息,目前遇到的问题是setsockopt()支持SO_REUSEADDR,但未定义SO_BROADCAST。
我已经用strings工具提取了入口点信息,头文件里包含大量套接字内部结构体,看起来必须操作这些内部结构才能实现需求。
基于net/netioc.h的分析
从提供的net/netioc.h文件来看,这套NRC套接字实现使用了一套自定义的el数组结构作为用户态和内核态的交互载体,_el_init()和_elc()是核心入口函数:
核心结构与函数
struct el:数据交互的基本单元,包含类型、标志、长度和两个通用字段,用于传递各种套接字操作的参数和数据。_el_init():初始化一个el数组,指定要执行的命令(比如ELC_SETOPT对应套接字选项设置)和标志。_elc():向el数组中添加一个新的el元素,用于传递具体参数(比如选项值、地址等)。
关键命令与选项
- 要实现类似SO_BROADCAST的功能,可以尝试使用
ELC_SETOPT命令(对应setsockopt()的功能),结合协议特定参数来设置广播权限。 - 以太网层面的广播/混杂模式可以通过ENIOC系列ioctl控制:
ENIOCNORMAL:接受广播和目标为本机的数据包ENIOCPROMISC:接受所有未损坏的数据包ENIOCALL:接受所有数据包(包括损坏的)
操作示例(伪代码)
如果要设置套接字的广播选项,可以按以下步骤操作:
// 1. 初始化el数组,指定ELC_SETOPT命令 struct el *el_array; el_array = el_init(NULL, ELC_SETOPT, 0); // 2. 添加要设置的选项参数(假设广播选项对应协议特定的P0参数) el_u(el_array, EL_P0, YOUR_BROADCAST_OPTION_VALUE); // 3. 调用net_ioctl(需要自己声明函数原型,比如int net_ioctl(int sock, int cmd, struct el *args);) int ret = net_ioctl(sock_fd, el_ioc(el_array), el_array);
注意事项
- 由于没有文档,需要通过
strings工具找到的入口点,结合ELC_*命令枚举测试不同参数的效果。 el_ioc()宏会根据el数组的元素数量生成对应的ioctl命令码,这是和内核交互的关键。
完整net/netioc.h内容
/* Copyright (C) 3/10/86 by Network Research Corporation * All rights reserved. No part of this software may be disclosed or distributed in any form or by any means without the prior written consent of Network Research Corporation. */ /* Module: h File: /nrc/rel/h/s.netioc.h */ /* Version 11.2 as of 86/03/10 at 10:31:12 */ #ifndef _NETIOC_ #define _NETIOC_ #ifndef _STD_ #include <net/std.h> #endif #define EL_VERSION 0 #define EL_MAX_SIZE 10 #ifndef SOIOCBASE #define SOIOCBASE ('s' << 8) #endif #ifndef SOIOCGNTTY #define SOIOCGNTTY (SOIOCBASE-2) #define SOIOCSNTTY (SOIOCBASE-1) #endif #ifndef SOIOCATMARK #define SOIOCATMARK (SOIOCBASE-3) /* for MSG_OOB */ #endif #ifndef ENIOCBASE #define ENIOCBASE ('e' << 8) #endif #ifndef INPIOCBASE #define INPIOCBASE ('i' << 8) #endif #define INPIOCDOWNLOAD (INPIOCBASE + 0) #define INPIOCEXECUTE (INPIOCBASE + 1) #define INPIOCINITIALIZE (INPIOCBASE + 2) #define INPIOCPROBE (INPIOCBASE + 3) #define INPIOCDIDDLE (INPIOCBASE + 4) /* Values for raw ethernet ioctls. These select the action inside * the link layer ioctl routine. */ #define ENIOCEND (ENIOCBASE+10) #define ENIOCNORMAL ENIOCBASE /* accept broadcast and specific */ #define ENIOCPROMISC (ENIOCBASE+1) /* accept all undamaged packets */ #define ENIOCALL (ENIOCBASE+2) /* accept ALL packets */ #define ENIOCRESET (ENIOCBASE+3) #ifdef MSDOS /* Raw socket driver interface ioctls for MSDOS only! */ #define SDIOCBASE ('o' << 8) #define SDIOCSTK SDIOCBASE /* give pre-sockdrv stack */ #endif MSDOS /* Defined values for el.el_u2.i field of el array header */ #define ELC_ACCEPT 0 /* accept a new connection */ #define ELC_ADDR 1 /* give back the current net address */ #define ELC_ASYNC 2 /* set/reset the socket as async */ #define ELC_ATTACH 3 /* attach to a protocol */ #define ELC_BETIMER 4 /* assume the timeout chores */ #define ELC_BIND 5 /* bind to a network address */ #define ELC_BLOCKING 6 /* turn off/on blocking */ #define ELC_CONNECT 7 /* actively seek connection */ #define ELC_DEBUG 8 /* network debugging entrypoint */ #define ELC_DIDDLE 9 /* peek/poke kernel variables */ #define ELC_EBDEV 10 /* external block device attach */ #define ELC_GETOPT 11 /* get protocol options now current */ #define ELC_INDEX 12 /* give/get the socket index */ #define ELC_LISTEN 13 /* listen for connection requests */ #define ELC_NEXTSOCKET 14 /* give me the next available socket index */ #define ELC_PAIR 15 /* activate the socketpair() code */ #define ELC_PEERADDR 16 /* deliver up the peer address */ #define ELC_RECV 17 /* recv a packet */ #define ELC_SEND 18 /* send a packet */ #define ELC_SETOPT 19 /* set protocol specific options */ #define ELC_SHUTDOWN 20 /* disallow read/write on socket */ #define ELC_SREAD 21 /* read data (used in VMS) */ #define ELC_SWRITE 22 /* write data (used in VMS) */ #define ELC_NSELECT 23 /* select available io on multiple sockets */ #define ELC_PIOCTL 24 /* protocol specific ioctl */ #define ELC_REJECT 25 /* reject a connection request */ #define EL_HEADER (0x4000 | EL_VERSION) #define EL_NOOP 0 #define EL_PROTOCOL 1 /* as in XNS_DGRAM */ #define EL_FAMILY 2 /* as in XNS, DARPA etc */ #define EL_INDEX 3 /* request/give a socket index */ #define EL_A_LEN 4 /* where to place the address length */ #define EL_D_LEN 5 /* where to place the data length */ #define EL_DATA 6 /* where's the beef? */ #define EL_DEST 7 /* destination network address */ #define EL_SRC 8 /* src network address */ #define EL_FLAGS 9 /* as in MSG_OOB MSG_PEEK etc. */ #define EL_TYPE 10 /* type field, interpreted by protocol */ #define EL_P0 11 /* protocol specific param 0 */ #define EL_P1 12 /* protocol specific param 1 */ #define EL_P2 13 /* protocol specific param 2 */ #define EL_P3 14 /* protocol specific param 3 */ #define EL_P4 15 /* protocol specific param 4 */ #define EL_PHDR 16 /* protocol header */ #define EL_PHLEN 17 /* protocol header length */ /* Flags for el.el_flags, musn't overlap common flag area (see <flags.h>) */ #define F_EL_STRUCTURED 0x1 /* structured data (32 bits) */ #define F_EL_IN 0x2 /* incoming (user ==> kernel) data element */ #define F_EL_OUT 0x4 /* outgoing (kernel ==> user) data element */ #define F_EL_KERNEL 0x8 /* element is in kernel space */ #define F_EL_ALLOC 0x10 /* element is in heap space -- must be freed */ #define F_EL_PROCESS 0x20 /* some additional processing to do */ #define F_EL_PPROCESS 0x40 /* don't free, more processing to do */ #define F_EL_MPRE_ALLOC 0x80 /* m structure is pre-allocate */ #define F_EL_KRESERVED F_EL_KERNEL /* el flags reserved for kernel use */ /* if the size of el changes fix el_cnt()!! */ typedef struct el { u16 el_type; u16 el_flags; u32 el_len; u32 el_u1; u32 el_u2; } el; import el * _elc(), * _el_init(); /* How many used. Expects size of an el to be 32 bytes */ #define el_cnt(elp1) (((int)((char *)elp1[0].el_u1 - (char *)(elp1))) >> 4) /* the next one available */ #define el_end(elp1) ((el *)(elp1)->el_u1) /* the last valid one */ #define el_last(elp1) (((el *)elp1->el_u1) - 1) /* size in bytes*/ #define el_size(elp1) (int)((char *)(elp1)[0].el_u1 - (char *)(elp1)) #define el_ioc(elp) ((SOIOCBASE-1)+el_cnt(elp)) #define el_u(elp, type, u1) \ _elc(elp, type, (u32)sizeof(u32), (u16)F_EL_STRUCTURED)->el_u1 = (u32)(u1) #ifdef KERNEL #define el_init(elp, cmnd, flags) \ _el_init(elp,(u32)(cmnd),(u16)flags| F_EL_KERNEL) #ifndef kcanonptr #define kcanonptr(p) ((u32)p) #endif #define el_ucp(elp, type, p, size, f) \ _elc(elp, type, (u32)(size), (u16)(f))->el_u1=((u32)p) #define el_cp(elp, type, p, size, f) \ _elc(elp, type, (u32)(size), (u16)(f)|(u16)F_EL_KERNEL)->el_u1=(kcanonptr(p)) #define el_up(elp, type, p, f) \ _elc(elp, type, (u32)sizeof(u32), (u16)(f)|(u16)(F_EL_STRUCTURED|F_EL_KERNEL))->el_u1=(kcanonptr(p)) #define el_xin(elp,kdest,c) ((elp[0].el_len==c)?el_in(elp,kdest,c):EINVAL) #define el_xout(elp,udest,c) ((elp[0].el_len==c)?el_out(elp,udest,c):EINVAL) #else KERNEL #define el_init(elp, cmnd, flags) _el_init(elp, (u32)(cmnd), (u16)flags) #ifndef canonptr #define canonptr(p) ((u32)p) #endif #define el_cp(elp, type, p, size, f) \ _elc(elp, type, (u32)(size), (u16)(f))->el_u1=(canonptr(p)) #define el_up(elp, type, p, f) \ _elc(elp, type, (u32)sizeof(u32), (u16)(f)|(u16)F_EL_STRUCTURED)->el_u1=(canonptr(p)) #endif KERNEL #endif _NETIOC_ /* * @(#)netioc.h 11.2 (NRC) */
内容的提问来源于stack exchange,提问作者Elektraglide
相关产品推荐
相关产品推荐

