Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tag: freebsd3_snap_…
Fetching contributors…

Cannot retrieve contributors at this time

file 295 lines (252 sloc) 11.191 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
Portability guideline
KAME project
$Id: PORTABILITY,v 1.40 2000/04/14 09:52:09 itojun Exp $


Source code in the "kame" directory will be shared among operating systems
and hardware platforms. Here are several guidelines to be portable
across those possibilities.

- Developers MUST compile the code on two or more platforms, before committing
  it to the repository (trivial changes or comment typos are okay).

- Do not break paren-match.
  Always try to keep paren-match correctly, regardless of #ifdef.
  The following is WRONG example:
#if foo
if (foo) {
#else
if (foo && bar) {
#endif
....
}

baz(this, that,
#if foo
something);
#else
something, anything);
#endif
  It should be written like follows:
#if foo
if (foo)
#else
if (foo && bar)
#endif
{
....
}

#ifdef foo
baz(this, that, something);
#else
baz(this, that, something, anything);
#endif

/* latter part can also be like follows... */
baz(this, that,
something
#ifndef foo
, anything
#endif
);

  It is also advised to add extra comment to help paren match,
  if you need to write widow paren in string. For example:
printf("("); /* ) */

- Avoid use of "#if" as much as possible, stick to "#ifdef" or "#ifndef"
  if possible (Avoid "#if defined(foo)" if you only have single "foo").
  "#if" is relatively new syntax and is not friendly with old tools like
  unifdef(1).

- Follow NetBSD KNF.
  They are the most strict guys about source code formatting.
  If you obey NetBSD KNF, other platforms are happy.
  More information on KNF is available at:
http://www.netbsd.org/Documentation/kernel/programming.html

- Pointer can be 64bit (for example, on alpha).
  When taking integer from pointer, use u_long, or long.
  This is WRONG:
void *p;
/* alignment check */
if ((1 & (int)p) == 0) {
...
}
  This is correct (but actually may not be future-proven):
void *p;
/* alignment check */
if ((1 & (u_long)p) == 0) {
...
}
  
- size_t can be 64bit, and may not be of same size as int.
  When doing printf(), cast size_t to u_long and print it as %lu.
size_t siz;
printf("%lu", (u_long)siz);
  Use of "%p" is more appropriate than casting, for pointers.

- If you would like to use printf() against variable typed u_quad_t,
  cast them to unsigned long long and use %llu.
u_quad_t x;
printf("%llu", (unsigned long long)x);
  %qu is outside of standard, and %llu is in C99 standard.

  Also note that FreeBSD prior to 3.2 cannot handle %llu correctly - you need
  to use %qu on these platforms (3.2 and later are okay).
  So you end up doing #ifdef __FreeBSD__.

  KAME libinet6 includes vfprintf() with %llu support where necessary,
  to ease code sharing in KAME userland code.

- tv.tv_sec is not typed as time_t.
  If you want time_t, explicitly copy the value.

- Packed structs must be used with care.
  Unaligned structure can cause problem on certain architectures.
  You'll need to copy the return value to aligned structure before accessing.

  Structure returned by SIOCGIFCONF falls into this category.

- 2nd arg to ioctl() must be u_long, not int, on non-FreeBSD2 platforms.

- If you define multi-statement #define, define that like:
#define foobar (x, y) \
do { \
/*something*/ \
/*something*/ \
} while (0)
  Without this wrapper nasty mistakes can happen.

- Compiler options need to be configured differently into Makefile.
  For NetBSD and OpenBSD, CFLAGS and CPPFLAGS are defined separately:
CPPFLAGS+=-I/usr/local/include
CFLAGS+=-g
  CPPFLAGS contains -I and -D only (those who needs to be passed to cpp).
  CFLAGS can contain other flags.
  For FreeBSD and BSDI, there's no distinction.
CFLAGS+=-I/usr/local/include
CFLAGS+=-g

- To refer objects and machine-generated source code, FreeBSD needs to use
  ${.OBJDIR}. This is because because FreeBSD completely separates "obj" tree
  and "src" tree and has no symlink from ${.CURDIR}/obj to /usr/obj/foobar.
  On other platforms, ${.CURDIR}/obj should do.

- On manpage installation and shlib generation in Makefile.
  for BSDI3, you need to set MAN[0-9] in Makefile like below. MANDIR must
  point to "catN" directory, not "manN", without "N":
MANDIR= /usr/local/v6/man/cat
MAN5= foo.0
MAN8= baz.0
MLINKS= foo.5 bar.5
  BSDI4 is much like the same as BSDI3. The only exception is shlib
  generation. NODYNAMIC=yes would prevent dynamic library from created:
MANDIR= /usr/local/v6/man/cat
MAN5= foo.0
MAN8= baz.0
MLINKS= foo.5 bar.5
NODYNAMIC=yes # if you do not want shlib, define it
  For NetBSD, you need to set MAN (not MAN[0-9]). MANDIR needs to point to
  "man" directory right above "catN" or "manN" directory:
MANDIR= /usr/local/v6/man
MAN= foo.5 baz.8
MLINKS= foo.5 bar.5
MKPIC= # if you do not want shlib, make it empty
  For OpenBSD, you need to set MAN (not MAN[0-9]). MANDIR needs to point to
  "catN" directory, without "N":
MANDIR= /usr/local/v6/man/cat
MAN= foo.5 baz.8
MLINKS= foo.5 bar.5
NOPIC= yes # if you do not want shlib, define it
  For FreeBSD, you need to set MAN[0-9] like below. MANDIR needs to point
  to "manN" directory, without "N":
MANDIR= /usr/local/v6/man/man
MAN5= foo.5
MAN8= baz.8
MLINKS= foo.5 bar.5
# if you do not want shlib, do not define SHLIB_{MAJOR,MINOR}

- If you use yacc/lex, be aware that FreeBSD bsd.prog.mk behaves very
  strange with yacc's -o option (non-trivial .if statement is placed).
  You may need to add the following into Makefile for code sharing.
  The following fragment will force the build to generate y.tab.h, instead
  of foo.h.
SRCS+=y.tab.h
y.tab.h: foo.y
  Be sure to include y.tab.h, not foo.h, from *.l.

- BSDI3 /usr/bin/cc is gcc 1.42, and it does not support __FUNCTION__.
  If you need to use __FUNCTION__, you need to set CC to "gcc", or "shlicc2"
  explicitly.
  __FUNCTION__ macro is not included in the ANSI standard, so it is best to
  avoid __FUNCTION__, or make it optional, for portability.

- sys/queue.h are very different in each of *BSDs. Most of macros found in
  FreeBSD3 are not available in other systems. Simply avoid those, make sure
  your code compile on non-FreeBSD3 systems.
  Avoid xx_FOREACH(), which is only available in FreeBSD3. Just use
for (x = xx_FIRST(); x; x = xx_NEXT(x))
  and do not try to make #if section for FreeBSD3. More #if introduces
  more bugs.

- It is better to avoid insque() and rmque(), they are from old VAX days
  and some platform now tries to avoid these.

- To identify FreeBSD3, use the following:
#if defined(__FreeBSD__) && __FreeBSD__ >= 3
this is freebsd3.
#endif

- To identify BSDI4, use the following:
#if defined(__bsdi__) && _BSDI_VERSION >= 199802
this is bsdi4.
#endif

- RFC2553 defines sockaddr_storage to have __ss_{family,len} member. During
  the discusson for the draft on ipngwg, ss_len was proposed and final result
  was not very clear. X/Open document mentions ss_len, not __ss_len.
  Therefore, you can see both definition on operating system platforms.
  The most portable way of dealing with it is to:
  (1) have -Dss_len=__ss_len to unify all occurences (including header file)
  into __ss_len, or (2) never touch __ss_len. cast to sockaddr * and use
  sa_len.

  Next version of RFC2553 (RFC2553bis) will define ss_len (not __ss_len),
  and be synchronized better with X/Open document.

- Never, never touch the __u6_addr{,8,16,32} member in struct in6_addr
  directly. Symbols starting with "__" are NOT supposed to be used.

- RFC2553 defines only s6_addr[16] (array of u_int8_t) as member of struct
  in6_addr. KAME strictly follows RFC2553, and does not provide any
  extensions like s6_addr{8,16,32} to the userland. For maximum portability
  across IPv6 platforms, only s6_addr should be used.
  In the future, we may provide s6_addr{8,16,32} to the userland when updates
  to RFC2553 defines them. They are, in fact, very convenient and we would
  like to see them defined in standard document.

- sysctl(3) support in kernel.
  FreeBSD: linker hack #define in sys/sysctl.h, like SYSCTL_INT().
no need to recompile sysctl(8).
SYSCTL_INT(_net_inet6_tcp6, TCP6CTL_SYN_CACHE_INTER,
syn_cache_interval, CTLFLAG_RW, &tcp6_syn_cache_interval, 0, "");
Note that sys/kernel.h should be included as well, which SYSCTL_XXX
macros depend.
  OpenBSD/NetBSD: xx_sysctl() needs to be supplied from inet6sw.
xx_sysctl() should implement switch statement to dispatch to all
possible leaf nodes available. symbols must be defined in header file
for use from sysctl(8).
  BSDI: similar to OpenBSD/NetBSD, but sysctl_int_arr() makes xx_sysctl()
code much easier for simple integer leaf nodes.

- Under BSD make tree (bsd.prog.mk), you can't use relative path against
  include files, like the following example:
#include "../foo/foo.h" /*THIS DOES NOT WORK*/
  If you are in baa/Makefile, and if you do "make obj", you will be in
  baa/obj when you build the tree. ../foo/foo.h will not be reachable
  (it will be interpreted as baa/obj/../foo/foo.h = baa/foo/foo.h)

  Solution: use -I${.CURDIR}/../foo.

- OpenBSD does not allow duplicated inclusion of system header files.
  (it does not have #ifndef _FOO_H_ wrapper)

- Developers are advised to use pedantic compilation options (like -Wall
  -Werror). To configure default make settings, /etc/make.conf (freebsd),
  /etc/mk.conf (netbsd/openbsd), and/or /usr/share/mk/sys.mk (bsdi) should be
  useful. Note, however, that the default compiler of bsdi3 (/usr/ucb/cc)
  does not suppport the -Werror option.

  Note that the meaning of -Wall is different across *BSD because *BSD use
  different version of gnu cc. Sometimes -Wall raises bogus warning due to
  bugs in code generator. Also, since function prototypes are defined
  differently in some cases (like ntohl), certain tweaks are needed to
  eliminate warnings on all the platforms. Don't worry about it too much,
  you can always talk with other developers.

- For portability in kernel networking code, look at kame/sys/net/net_osdep.h.

- The -interface modifier of the route(8) command does not take an
  argument except on FreeBSD. Also, the original FreeBSD's extension
  has several bugs (although those bugs are fixed in the route command
  in the KAME kit). If you regard portability and stability, it would
  be better to use an IPv6 link-local address on the interface as
  gateway.

  For example,
  # route add -inet6 default -interface gif0 (on FreeBSD)
  is equivalent to
  # route add -inet6 default `ifconfig gif0 | grep fe80 | awk '{print $2}'`
  If you care about cases that gif0 has more than one link-local address,
  you might have to type
  # route add -inet6 default `ifconfig gif0 | grep fe80 | head -1 | awk '{print $2}'`
  Note that this kind of approach assumes that gif0 has at least one
  IPv6 link-local address. If you are not sure about this, you might
  want to execute
  # ifconfig gif0 up
  before executing the route command.

  BSDI4 users can take the following approach as well:
  # route add -inet6 default ::1 -ifp gif0
  which would be much simpler. This is because BSDI4 has improved
  kernel code of handling routing sockets. We will eventually merge
  this improvement into other OSes.
Something went wrong with that request. Please try again.