Re: Socket header file

Andrew Pollard (andrew@odie.demon.co.uk)
Thu, 19 Dec 1996 17:19:26 GMT


Alan Modra writes:

> >Richard Gooch <rgooch@atnf.CSIRO.AU>
> >
> > Alan Modra writes:
> > >
> > > >root@analogic.com (Richard B. Johnson)
> > > > /usr/include/linux/socket.h: unsigned char cmsg_data[0];
> > > > This should probably be:
> > > > unsigned char *cmsg_data;
> > >
> > > No, definitely not. It's correct as it is. The structure is
> > > dynamically allocated with cmsg_data[] a variable length array.
> >
> > I have complained to Linus about this a few times before, with no
> > response. The problem with the above construct is that you cannot
> > compile with gcc -Wall -pedantic-errors
>
> Glad to see that you like to have your code portable. Linus may
> accept a fix rather than just a complaint. No, come to think of it,
> the person you should talk to is Alan Cox, since he's the network code
> maintainer.
>
> One fix would be to zap cmsg_data[0] from struct cmsghdr, change the
> CMSG_DATA define to
> #define CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + sizeof(struct cmsghdr))
> and fix kernel code referencing cmsg_data. In fact, the CMSG_DATA
> macro should be used in the kernel anyway. Shouldn't take more than
> 10 minutes :-)

I've been having this problem as well. Here is implementation of
suggested fix for 2.1.16 (haven't tried compiling it though, think I
got all the references :-)

diff -r -u v2.1.16/include/linux/socket.h linux/include/linux/socket.h
--- v2.1.16/include/linux/socket.h Fri Dec 13 13:31:42 1996
+++ linux/include/linux/socket.h Thu Dec 19 16:53:58 1996
@@ -50,7 +50,7 @@
size_t cmsg_len; /* data byte count, including hdr */
int cmsg_level; /* originating protocol */
int cmsg_type; /* protocol-specific type */
- unsigned char cmsg_data[0];
+/* unsigned char cmsg_data[0]; *//* handled by CMSG_DATA macro below */
};

/*
@@ -58,7 +58,7 @@
* Table 5-14 of POSIX 1003.1g
*/

-#define CMSG_DATA(cmsg) (cmsg)->cmsg_data
+#define CMSG_DATA(cmsg) ((unsigned char *)(cmsg)+sizeof(struct cmsghdr))
#define CMSG_NXTHDR(mhdr, cmsg) cmsg_nxthdr(mhdr, cmsg)

#define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
diff -r -u v2.1.16/net/core/scm.c linux/net/core/scm.c
--- v2.1.16/net/core/scm.c Fri Dec 13 13:31:49 1996
+++ linux/net/core/scm.c Thu Dec 19 17:00:03 1996
@@ -60,7 +60,7 @@
int num;
struct scm_fp_list *fpl = *fplp;
struct file **fpp = &fpl->fp[fpl->count];
- int *fdp = (int*)cmsg->cmsg_data;
+ int *fdp = (int*)CMSG_DATA(cmsg);
int i;

num = (cmsg->cmsg_len - sizeof(struct cmsghdr))/sizeof(int);
@@ -161,7 +161,7 @@
case SCM_CREDENTIALS:
if (kcm.cmsg_len < sizeof(kcm) + sizeof(struct ucred))
goto error;
- memcpy(&p->creds, cmsg->cmsg_data, sizeof(struct ucred));
+ memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred));
err = scm_check_creds(&p->creds);
if (err)
goto error;
@@ -171,7 +171,7 @@
goto error;
if (kcm.cmsg_len < sizeof(kcm) + sizeof(int))
goto error;
- memcpy(&acc_fd, cmsg->cmsg_data, sizeof(int));
+ memcpy(&acc_fd, CMSG_DATA(cmsg), sizeof(int));

p->sock = NULL;
if (acc_fd != -1) {
@@ -229,7 +229,7 @@
cm->cmsg_level = level;
cm->cmsg_type = type;
cm->cmsg_len = cmlen;
- memcpy(cm->cmsg_data, data, cmlen - sizeof(*cm));
+ memcpy(CMSG_DATA(cm), data, cmlen - sizeof(*cm));

cmlen = CMSG_ALIGN(cmlen);
msg->msg_control += cmlen;
@@ -250,7 +250,7 @@
if (fdnum > fdmax)
fdmax = fdnum;

- for (i=0, cmfptr=(int*)cm->cmsg_data; i<fdmax; i++, cmfptr++)
+ for (i=0, cmfptr=(int*)CMSG_DATA(cm); i<fdmax; i++, cmfptr++)
{
int new_fd = get_unused_fd();
if (new_fd < 0)
diff -r -u v2.1.16/net/ipv4/ip_sockglue.c linux/net/ipv4/ip_sockglue.c
--- v2.1.16/net/ipv4/ip_sockglue.c Fri Dec 13 13:31:52 1996
+++ linux/net/ipv4/ip_sockglue.c Thu Dec 19 17:00:48 1996
@@ -127,12 +127,12 @@
case IP_LOCALADDR:
if (kcm.cmsg_len < sizeof(struct in_addr)+sizeof(kcm))
return -EINVAL;
- if (copy_from_user(&ipc->addr, cmsg->cmsg_data, 4))
+ if (copy_from_user(&ipc->addr, CMSG_DATA(cmsg), 4))
return -EFAULT;
break;
case IP_RETOPTS:
err = kcm.cmsg_len - sizeof(kcm);
- err = ip_options_getfromuser(&ipc->opt, cmsg->cmsg_data,
+ err = ip_options_getfromuser(&ipc->opt, CMSG_DATA(cmsg),
err < 40 ? err : 40);
if (err)
return err;
@@ -142,7 +142,7 @@
return -EINVAL;
if (!devp)
return -EINVAL;
- if (copy_from_user(devname, cmsg->cmsg_data, MAX_ADDR_LEN-1))
+ if (copy_from_user(devname, CMSG_DATA(cmsg), MAX_ADDR_LEN-1))
return -EFAULT;
devname[MAX_ADDR_LEN-1] = 0;
if ((*devp = dev_get(devname)) == NULL)
diff -r -u v2.1.16/net/ipv6/datagram.c linux/net/ipv6/datagram.c
--- v2.1.16/net/ipv6/datagram.c Fri Dec 13 13:31:57 1996
+++ linux/net/ipv6/datagram.c Thu Dec 19 17:01:34 1996
@@ -47,7 +47,7 @@
cmsg->cmsg_level = SOL_IPV6;
cmsg->cmsg_type = IPV6_RXINFO;

- src_info = (struct in6_pktinfo *) cmsg->cmsg_data;
+ src_info = (struct in6_pktinfo *) CMSG_DATA(cmsg);
in6_dev = ipv6_get_idev(skb->dev);

if (in6_dev == NULL)
@@ -77,7 +77,7 @@
cmsg->cmsg_level = SOL_IPV6;
cmsg->cmsg_type = IPV6_RXINFO;

- rt0 = (struct rt0_hdr *) cmsg->cmsg_data;
+ rt0 = (struct rt0_hdr *) CMSG_DATA(cmsg);
memcpy(rt0, opt->srcrt, hdrlen);

len -= cmsg->cmsg_len;
@@ -116,7 +116,7 @@
goto exit_f;
}

- src_info = (struct in6_pktinfo *) cmsg->cmsg_data;
+ src_info = (struct in6_pktinfo *) CMSG_DATA(cmsg);

if (src_info->ipi6_ifindex)
{
@@ -158,7 +158,7 @@
goto exit_f;
}

- rthdr = (struct ipv6_rt_hdr *) cmsg->cmsg_data;
+ rthdr = (struct ipv6_rt_hdr *) CMSG_DATA(cmsg);

/*
* TYPE 0

Andrew
=============================================================================
| Andrew Pollard, Integral Solutions Ltd UK.| Work: andrewp@isl.co.uk |
| Tel:+44(0)1256 55899 Fax:+44(0)1256 63467 | Home: andrew@odie.demon.co.uk |
=============================================================================