pcap 라이브러리



pacp_open_live() : 네트워크 디바이스 열기

pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)

  • device : 디바이스 이름 (eth0, hme0)
  • snplen : 한번에 캡쳐할 크기 지정
  • promisc : 캡쳐할 대상
    • 0 : 목적지가 자신, 브로드 캐스트, 자신포함한 멀티 캐스트
    • 1 : 모든 패킷
  • to_ms : 버퍼링 시간, 패킷 도착후 OS가 처리 대기 시간
    • 0 : 충분히 패킷 도착 할
2007/10/06 07:36 2007/10/06 07:36
Tag //

IPv4용 소스를 IPv6로 바꿀

2006/07/25 10:40 2006/07/25 10:40

IPv6변환을 위해 연습 했던 소스


1.1 IPv4 클라이언트 소스

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#define BUFSIZE 1024

void error_handling(char *);

void

error_handling(char *message)

{
fputs(message, stderr);
fputc('\n', stderr);       
exit(1);
}

int main (int argc, char *argv[])
{
       int sock;
       struct sockaddr_in serv_addr;

    

       char message[BUFSIZE];
       int len;
       int add;

       if (argc != 3) {
       printf("usage : %s <server's IP> <port>\n", argv[0]);
       exit(1);
}

       sock = socket(PF_INET, SOCK_STREAM, 0);
       if (sock == -1)
       error_handling("socket() error");

       memset(&serv_addr, 0, sizeof(serv_addr));
       serv_addr.sin_family = AF_INET;
       serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
       serv_addr.sin_port = htons(atoi(argv[2]));

        if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
               error_handling("accept() error");

       while (1)
       {      
               fputs("\nInput number to send(q to quit) : ", stdout);
               fgets(message, BUFSIZE, stdin);

               if (!strcmp(message, "q\n"))
                       break;

               write(sock, message, strlen(message));

               len = read(sock, message, BUFSIZE-1);
               message[len] = 0;

               printf("Added Number from Server : %s\n", message);
}

       close(sock);
       return 0;

       }

1.2 IPv4 서버

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define BUFSIZE 1024

void error_handling(char *);

void

error_handling(char *message)

{
fputs(message, stderr);
fputc('\n', stderr);       
exit(1);
}

int main (int argc, char *argv[])
{
       int serv_sock, clnt_sock;
       struct sockaddr_in serv_addr, clnt_addr;

       int clnt_addr_size;

       char message[BUFSIZE];
       int len;
       int add;

       if (argc != 2) {
       printf("usage : %s <port>\n", argv[0]);
       exit(1);
}

       serv_sock = socket(PF_INET, SOCK_STREAM, 0);
       if (serv_sock == -1)
       error_handling("socket() error");

        memset(&serv_addr, 0, sizeof(serv_addr));
       serv_addr.sin_family = AF_INET;
       serv_addr.sin_addr.s_addr = inet_addr("10.51.12.166");
       serv_addr.sin_port = htons(atoi(argv[1]));

       if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
       error_handling("bind() error");

       if (listen(serv_sock, 5) == -1 )
       error_handling("listen() error");

       printf("server started!!(%s)\n", argv[1]);

       clnt_addr_size = sizeof(clnt_addr);
       clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr,&clnt_addr_size);
       if (clnt_sock == -1)
       error_handling("accept() error");

       printf("clnt connected!!(%s:%d)\n",
       inet_ntoa(clnt_addr.sin_addr), clnt_addr.sin_port);

       int buf=0;
       while ((len = read(clnt_sock, message, BUFSIZE)) != 0) {
      
               buf+=atoi(message);
               sprintf(message, "%d", buf);
               len = strlen(message);
               write(clnt_sock, message, len);
       }

       printf("server terminated\n");

       close(clnt_sock);

       return 0;

}

2.1 IPv6 클라이언트

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#define BUFSIZE 1024

void error_handling(char *);

void

error_handling(char *message)

{
fputs(message, stderr);
fputc('\n', stderr);       
exit(1);
}

int main (int argc, char *argv[])
{
       int sock;
       struct sockaddr_in6 serv_addr;

    

       char message[BUFSIZE];
       int len;
       int add;

       if (argc != 3) {
       printf("usage : %s <server's IP> <port>\n", argv[0]);
       exit(1);
}

       sock = socket(PF_INET6, SOCK_STREAM, 0);
       if (sock == -1)
       error_handling("socket() error");

       memset(&serv_addr, 0, sizeof(serv_addr));
       serv_addr.sin6_family = AF_INET6;
       serv_addr.sin6_addr = in6addr_any;
       serv_addr.sin6_port = htons(atoi(argv[2]));

        if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
               error_handling("accept() error");

       while (1)
       {      
               fputs("\nInput number to send(q to quit) : ", stdout);
               fgets(message, BUFSIZE, stdin);

               if (!strcmp(message, "q\n"))
                       break;

               write(sock, message, strlen(message));

               len = read(sock, message, BUFSIZE-1);
               message[len] = 0;

               printf("Added Number from Server : %s\n", message);
}

       close(sock);
       return 0;

       }



2.2 IPv6서버

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define BUFSIZE 1024

void error_handling(char *);

void

error_handling(char *message)

{
fputs(message, stderr);
fputc('\n', stderr);       
exit(1);
}

int main (int argc, char *argv[])
{
       int serv_sock, clnt_sock;
       struct sockaddr_in6 serv_addr, clnt_addr;

       int clnt_addr_size;

       char message[BUFSIZE];
       int len;
       int add;

       if (argc != 2) {
       printf("usage : %s <port>\n", argv[0]);
       exit(1);
}

       serv_sock = socket(PF_INET6, SOCK_STREAM, 0);
       if (serv_sock == -1)
       error_handling("socket() error");

        memset(&serv_addr, 0, sizeof(serv_addr));
       serv_addr.sin6_family = AF_INET6;
       serv_addr.sin6_flowinfo = 0;
       serv_addr.sin6_addr = in6addr_any;
       serv_addr.sin6_port = htons(atoi(argv[1]));

       if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) == -1)
       error_handling("bind() error");

       if (listen(serv_sock, 5) == -1 )
       error_handling("listen() error");

       printf("\nserver started!!(%s)\n", argv[1]);

       clnt_addr_size = sizeof(clnt_addr);
       clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr,&clnt_addr_size);
       if (clnt_sock == -1)
       error_handling("accept() error");

       printf("\nclnt connected!!\n"
       );

       int buf=0;
       while ((len = read(clnt_sock, message, BUFSIZE)) != 0) {
      
               buf+=atoi(message);
               sprintf(message, "%d", buf);
               len = strlen(message);
               write(clnt_sock, message, len);
       }

       printf("\nserver terminated!!!\n");

       close(clnt_sock);

       return 0;

}




작성일 : 2006.07.14
작성자 : 임헌정
http://www.4ellene.net

2006/07/14 15:55 2006/07/14 15:55
Tag //

Implementing AF-independent application

Jun-ichiro itojun Itoh, KAME Project
$Id: index.html,v 1.3 2003/05/16 15:42:36 itojun Exp $

Introduction

By deployment of Internet Protocol Version 6 (IPv6), the application programmers has to cope with socket connection with multiple address families, i.e. AF_INET and AF_INET6. The document describes how a programmer can handle those multiple address families at ease.

This document assumes that you are familiar with AF_INET socket programming. You may want to refer RFC2553 and RFC2292.

If you find any mistakes, please let the author know. The document will be updated right away. Thank you!


struct sockaddr_storage

RFC2553 proposes struct sockaddr_storage. This is a placeholder for all sockaddr-variant structures. This is implemented like follows:
	struct sockaddr_storage {		u_char ss_len;		u_char ss_family;		u_char padding[128 - 2];	};
You should use this structure to hold any of sockaddr-variant structures.

union sockunion

Alternatively, you may want to implement sockunion.h, with the following content:
	union sockunion {		struct sockinet {			u_char si_len;			u_char si_family;		} su_si;		struct sockaddr_in  su_sin;		struct sockaddr_in6 su_sin6;	};	#define su_len        su_si.si_len	#define su_family     su_si.si_family
NOTE: For better portability, struct sockaddr_storage should be used. union sockunion is okay, but is not really portable enough due to structure alignment twists.

Rules of thumb

1. avoid struct in_addr and struct in6_addr.

Since we are trying to implement AF-independent programs, all of the memory structures that handle network address have to be AF-independent. In that sense, we should avoid struct in_addr and in6_addr, since they have no room to hold AF information. Suppose you pass an network address to some function, foo(). If you use struct in_addr or struct in6_addr, you will end up with extra parameter to indicate address family, as below:
	struct in_addr in4addr;	struct in6_addr in6addr;	/* IPv4 case */	foo(&in4addr, AF_INET);	/* IPv6 case */	foo(&in6addr, AF_INET6);
This way the network address and address family is will not live together, and leads to bunch of if/switch statement and mistakes in programming. Why don't we just use struct sockaddr_storage like below?
	struct sockaddr_storage ss;	int sslen;	/* AF independent! - use sockaddr when passing a pointer */	foo((struct sockaddr *)&ss);	/* if you need portability to Linux/Solaris, you need to pass length explicitly */	foo((struct sockaddr *)&ss, sslen);
Also, by near-future update to IPv6 basic socket API (RFC2553), sockaddr_in6 will include interface index for link-local scoped address, as well as site index for site-local scoped address. Therefore, if your application needs to handle scoped addresses, avoiding in6_addr (and using sockaddr_in6) is a critical requirement.

2. use getaddrinfo() and getnameinfo() everywhere.

getaddrinfo() and getnameinfo() are new address independent variant that hides every gory detail in name-to-address translation, or vice versa. It implements functionalities for the following functions:
	gethostbyname()	gethostbyaddr()	inet_ntop()	inet_pton()	getservbyname()	getservbyport()
These can perform DNS/hostname table lookup, though it can be turned off if you want. getaddrinfo() can return multiple addresses, if a host have multiple address with multiple address families, as below:
	localhost.	IN A	127.0.0.1			IN AAAA	::1
It can query hostname as well as service name/port at once. Therefore, we can bury all the gory details about initializing sockaddr structure into library function.

Anyway. inet_aton() can be written as follows:

	int error;	char *name;	struct sockaddr_storage ss;	struct sockaddr *sa;	struct addrinfo hints;	struct addrinfo *res;	/*	 * inet_aton() case.	 * This cannot handle IPv6 addresses.  Also, it cannot return	 * multiple addresses.	 */	if (!inet_aton(name, &((struct sockaddr_in *)&ss)->sin_addr))		perror("inet_aton");	/* getaddrinfo() case.  It can handle multiple addresses. */	memset(&hints, 0, sizeof(hints));	/* set-up hints structure */	hints.ai_family = PF_UNSPEC;	error = getaddrinfo(name, NULL, &hints, &res);	if (error)		perror(gai_strerror(error));	else {		while (res) {			sa = res->ai_addr;			salen = res->ai_addrlen;			/* do what you want */			res = res->ai_next;		}	}
inet_ntoa() can be written as follows:
	int error;	char *name;	char namebuf[BUFSIZ];	struct sockaddr_storage ss;	/*	 * inet_ntoa() case. This cannot handle IPv6 addresses.	 * No way to pass the error status.	 */	name = inet_ntoa(((struct sockaddr_in *)&ss)->sin_addr);	/* getnameinfo() case. NI_NUMERICHOST avoids DNS lookup. */	error = getnameinfo((struct sockaddr *)&ss. ss.ss_len,		namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST);	if (error)		perror("getnameinfo");	name = namebuf;
gethostbyname() can be written as follows:
	struct sockaddr *sa;	struct hostent *hp;	char *name;	int af;	struct addrinfo hints;	struct addrinfo *res;	/* gethostbyname() case.  It is just for single AF denoted by "af". */	hp = gethostbyname2(name, af);	/*	 * getaddrinfo() case.  You can get IPv6 address and IPv4 address	 * at the same time.	 */	memset(&hints, 0, sizeof(hints));	/* set-up hints structure */	hints.ai_family = PF_UNSPEC;	error = getaddrinfo(name, NULL, &hints, &res);	if (error)		perror(gai_strerror(error));	else {		while (res) {			sa = res->ai_addr;			salen = res->ai_addrlen;			/* do what you want */			res = res->ai_next;		}	}
Now, gethostbyaddr() can be written as follows:
	struct sockaddr_storage ss;	struct sockaddr_in *sin;	struct sockaddr_in6 *sin6;	struct hostent *hp;	char *name;	/* gethostbyaddr() case. */	switch (ss.ss_family) {	case AF_INET:		sin = (struct sockaddr_in *)&ss;		hp = gethostbyaddr(&sin->sin_addr, sizeof(sin->sin_addr),			ss.ss_family);		break;	case AF_INET6:		sin6 = (struct sockaddr_in6 *)&ss;		hp = gethostbyaddr(&sin6->sin6_addr, sizeof(sin6->sin6_addr),			ss.ss_family);		break;	}	name = hp->h_name;	/* getnameinfo() case. NI_NUMERICHOST avoids DNS lookup. */	error = getnameinfo((struct sockadddr *)&ss, ss.ss_len,		namebuf, sizeof(namebuf), NULL, 0, 0);	if (error)		perror("getnameinfo");	name = namebuf;

3. do not hardcode knowledge about particular AF.

Since we are trying to be AF-independent, it is not preferred to hardcode AF-dependent knowledge into the program. The construct like below should be avoided:
	/* BAD EXAMPLE */	switch (sa->sa_family) {	case AF_INET:		salen = sizeof(struct sockaddr_in);		break;	}
Instead, use res->ai_addrlen returned by getaddrinfo(3).

Modifying servers called from inetd

To port your server that is called via inetd (for example, pop server), you must rewrite the following portions:
  1. all struct sockaddr_in has to be changed into struct sockaddr_storage. Be sure to update cast operators and sizeof operations as well. Pointers should be changed into struct sockaddr *.
  2. rewrite struct/union field names.
  3. inet_aton() and inet_ntoa() has to be changed to getaddrinfo() and getnameinfo().
  4. gethostbyname() and gethostbyaddr() has to be changed to getnameinfo() and getaddrinfo().
The simplest server has no sockaddr-related code inside, it will just use standard input. However, most servers has logging functionality, which requires the address for the peer. It will be obtained by using getpeername(). Therefore, you must rewrite address-to-name translation part for peer address.

Use great care on sizeof operation to sockaddr. This kind of code is very popular:

	int slen;	struct sockaddr_in sin;	slen = sizeof(struct sockaddr_in);	getsockname(s, (struct sockaddr *)&sin, &slen);
If we simply modify the type of sin, we're doomed. You'll need to change sizeof operation as well, like:
	int slen;	struct sockaddr_storeage ss;	slen = sizeof(ss);	getsockname(s, (struct sockaddr *)&ss, &slen);

Modifying daemons

IPv4 daemons usually bind to IN_ADDR_ANY, that is, 0.0.0.0. To obtain this kind of address in a AF-independent manner, you can use AI_PASSIVE flag for getaddrinfo(). Mutliprotocol daemon may want to bind() to all the addresses returned from getaddrinfo().
	struct addrinfo hints;	struct addrinfo *res;	char *myservice;	memset(&hints, 0, sizeof(hints));	/* set-up hints structure */	hints.ai_family = PF_UNSPEC;	hints.ai_flags = AI_PASSIVE;	hints.ai_socktype = SOCK_STREAM;	error = getaddrinfo(NULL, myservice, &hints, &res);	if (error)		perror(gai_strerror(error));	else {		/*		 * "res" has a chain of addrinfo structure filled with		 * 0.0.0.0 (for IPv4), 0:0:0:0:0:0:0:0 (for IPv6) and alike,		 * with port filled for "myservice".		 */		while (res) {			/* bind() and listen() to res->ai_addr */		}	}

Modifying clients

Client side program may want to connect to all resolved addresses, as telnet program does (telnet tries to connect to all resolved addresses, sequentially until connection is established).
	struct addrinfo hints;	struct addrinfo *res;	char *server;	char *hisservice;	memset(&hints, 0, sizeof(hints));	/* set-up hints structure */	hints.ai_family = PF_UNSPEC;	hints.ai_socktype = SOCK_STREAM;	error = getaddrinfo(server, hisservice, &hints, &res);	if (error)		perror(gai_strerror(error));	else {		while (res) {			/* try to connect() to res->ai_addr */			if (success)				break;		}	}	/* whatever you would like to perform */

What about inet_ntop() and inet_pton()?

In previous sections, we talked almost nothing about the usage of inet_ntop() and inet_pton(). This is because they are not very AF independent. Since inet_ntoa() and inet_aton() are just for IPv4 addresses, inet_ntop() and inet_pton() are described as replacement, in RFC2553. They are defined as follows:
	int inet_pton(int af, const char *src, void *dst);	const char *inet_ntop(int af, const void *src,		char *dst, size_t size);
inet_pton() and inet_ntop() assumes in_addr or in6_addr for handling addresses, that are, as I wrote, something we would like to avoid. If you got a some sockaddr-ish structure, you can get printable form of address by the following statements.
	struct sockaddr_storage ss;	char buf[BUFLEN];	switch (ss.ss_family) {	case AF_INET:		inet_ntop(ss.ss_family,			&((struct sockaddr_in *)&ss)->sin_addr, buf, BUFLEN);		break;	case AF_INET6:		inet_ntop(ss.ss_family,			&((struct sockaddr_in6 *)&ss)->sin6_addr, buf, BUFLEN);		break;	}
This requires extra conditional statement, since inet_ntop() is not written for sockaddr structures. Worse, for converting printable form into address, you need to konw the address family, prior to the call to inet_pton(). You can perform error-and-retly loop but it is not a very clean way of dealing with it.
	struct sockaddr_storage ss;	struct sockaddr_in *sin;	struct sockaddr_in6 *sin6;	char *printable;	switch (ss.ss_family) {	case AF_INET:		sin = (struct sockaddr_in *)&ss;		inet_pton(af, printable, &sin->sin_addr));		break;	case AF_INET6:		inet_pton(af, printable, &sin6->sin6_addr);		break;	}
Answer: You should use getnameinfo whereever possible.

update history

  • November 1998: document struct sockaddr_storage.
  • December 1998: replace union sockunion into struct sockaddr_storage, as struct sockaddr_storage is recommended.
  • July 1999: comment out most of union sockunion part. Thank Mr. Adam M. Costello for comment.
  • November 2000: update draft #.

KAME top page
Copyright (c) 1998, 1999, 2000, 2001, 2002, and 2003 by the author (indicated separately). All rights reserved. Freely redistributable. Absolutely no warranty.


출처 : http://www.kame.net/newsletter/19980604/
2006/07/14 11:29 2006/07/14 11:29
Tag //
1. BSD (출처 : DEVPIA 곽용진님) style  APIs

1.1 Transformation Functions

htonl
htons
inet_addr
inet_ntoa
ntohl
ntohs

1.2 DataBase Functions

gethostbyaddr
gethostbyname
gethostname
getprotobyname
getprotobynumber
getservbyname
getservbyport

1.3 Socket Functions

accept
bind
closesocket
connect
getpeername
getsockname
getsockopt
ioctlsocket
listen
recv
recvfrom
select
send
sendto
setsockopt
shutdown
socket


2. Windows  Socket  Extension  APIs

2.1 Transformation Functions

WSAHtonl
WSANtohl
WSAHtons
WSANtohs

2.2 DataBase Functions

WSAAsyncGetHostByAddr
WSAAsyncGetHostByName
WSAAsyncGetProtoByName
WSAAsyncGetProtoByNumber
WSAAsyncGetServByName
WSAAsyncGetServByPort
WSAEnumProtocols

2.3 Socket Functions

WSAAsyncSelect
WSACancelAsyncRequest
WSACancelBlockingCall
WSACleanup
WSAGetLastError
WSAIsBlocking
WSASetBlockingHook
WSASetLastError
WSAStartup
WSAUnhookBlockingHook
WSAEventSelect
WSAAccept
WSASend
WSASendTo
WSARecv
WSARecvFrom
WSAConnect
WSAloctl
WSAJoinLeaf
WSARecvEx
WSASocket
WSAWaitForMultipleEvents
WSAEnumNetworkEvents
WSACreateEvent
WSAGetOverlappedResult
WSASetEvent
WSAResetEvent


3. Socket  Structures

SOCKADDR
SOCKADDR_IN
IN_ADDR
HOSTENT
PROTOENT
SERVENT
LINGER
FD_SET
TIMEVAL
WSADATA
WSABUF
WSAOVERLAPPED
WSAPROTOCOL_INFO
WSANETWORKEVENTS

2006/07/09 23:51 2006/07/09 23:51
Chapter 1Provides an overview of XTI, STREAMS, sockets, and the programming tasks required for network applications.
Chapter 2Describes the dlb pseudodriver, which implements a subset of the the Data Link Provider Interface (DLPI).
Chapter 3Describes the fundamental concepts associated with XTI, how to write connection-oriented and connectionless applications, compatibility issues with TLI, and how to port applications to XTI. XTI errors are also covered in this chapter.
Chapter 4Describes the concepts associated with the socket interface, and how to write socket applications.
Chapter 5Describes Tru64 UNIX implementation of STREAMS.
Chapter 6Describes the Extensible System Network Management Application Programming Interface.
Chapter 7Describes the Resource ReSerVation Protocol Application Programming Interface.
Chapter 8Describes the ifnet STREAMS module and dlb STREAMS pseudodriver communication bridges.
Appendix AProvides a sample STREAMS module.
Appendix BProvides XTI and sockets programming examples.
Appendix CProvides AF_INET and AF_INET6 sockets programming examples.
Appendix DProvides Transport Protocol Control (TCP) specific programming information.
Appendix EProvides information required by token ring driver developers.
Appendix FDescribes the Data Link Interface (DLI) and provides programming examples.

링크 : http://www.helsinki.fi/atk/unix/dec_manuals/DOC_51A/HTML/ARH9UDTE/INDEX.HTM
2006/07/06 19:47 2006/07/06 19:47

Programming with sockets Porting IPv6 -- examples

Consider the following IPv4 code examples:

IPv4 client code

  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <stdio.h>
  #include <netdb.h>
   ...
  main(argc, argv) /* client side */
   int argc;
   char *argv[];
  {
   struct sockaddr_in server;
   struct servent *sp;
   struct hostent *hp;
   int s;
   ...
   sp = getservbyname("login", "tcp");
   if (sp == NULL) {
    fprintf(stderr, "rlogin: tcp/login: unknown service\n");
    exit(1);
   }
   hp = gethostbyname(argv[1]);
   if (hp == NULL) {
    fprintf(stderr, "rlogin: %s: unknown host\n", argv[1]);
    exit(2);
   }
   memset((char *)&server, 0, sizeof(server));
   memcpy((char *)&server.sin_addr, hp->h_addr, hp->h_length);
   server.sin_len = sizeof(server);
   server.sin_family = hp->h_addrtype;
   server.sin_port = sp->s_port;
   s = socket(AF_INET, SOCK_STREAM, 0);
   if (s < 0) {
    perror("rlogin: socket");
    exit(3);
   }
   ...
   /* Connect does the bind for us */
   if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0) {
    perror("rlogin: connect");
    exit(5);
   }
   ...
   exit(0);
  }

IPv4 server code

  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <stdio.h>
  #include <netdb.h>
   ...
  main(argc, argv) /* server side */
   int argc;
   char *argv[];
  {
   int f;
   struct sockaddr_in from;
   struct sockaddr_in sin;
   struct servent *sp;
 
   sp = getservbyname("login", "tcp");
   if (sp == NULL) {
    fprintf(stderr,
     "rlogind: tcp/login: unknown service\n");
    exit(1);
   }
   ...
  #ifndef DEBUG
   /* Disassociate server from controlling terminal. */
   ...
  #endif
 
   memset((char *)&sin, 0, sizeof(sin));
   sin.sin_len = sizeof(sockaddr_in);
   sin.sin_port = sp->s_port; /* Restricted port */
   sin.sin_addr.s_addr = INADDR_ANY;
   ...
   f = socket(AF_INET, SOCK_STREAM, 0);
   ...
   if (bind(f, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
    ...
   }
   ...
   listen(f, 5);
   for (;;) {
    int g, len = sizeof(from);
 
    g = accept(f, (struct sockaddr *) &from, &len);
    if (g < 0) {
     if (errno != EINTR)
      syslog(LOG_ERR, "rlogind: accept: %m");
     continue;
    }
    if (fork() == 0) {
     close(f);
     doit(g, &from);
    }
    close(g);
   }
   exit(0);
  }

This code can be ported to IPv6 with only a small number of changes. These changes are highlighted in the examples below by comments in the code.

IPv4 client code ported to IPv6

  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <stdio.h>
  #include <netdb.h>
   ...
  main(argc, argv) /* client side */
   int argc;
   char *argv[];
  {
   /*                                                    */
   /* OLD code: struct sockaddr_in server;               */
   /*                                                    */
   /* Change structure to sockaddr_in6 from sockaddr_in. */
   /*                                                    */
   struct sockaddr_in6 server;
   struct servent *sp;
   struct hostent *hp;
   int s;
   ...
   sp = getservbyname("login", "tcp");
   if (sp == NULL) {
    fprintf(stderr, "rlogin: tcp/login: unknown service\n");
    exit(1);
   }
 
   /*                                                    */
   /* OLD code: hp = gethostbyname(argv[1]);             */
   /*                                                    */
   /* Use gethostbyname2 instead of gethostbyname.       */
   /*                                                    */
   hp = gethostbyname2(argv[1], AF_INET6);
   if (hp == NULL) {
    fprintf(stderr, "rlogin: %s: unknown host\n", argv[1]);
    exit(2);
   }
   memset((char *)&server, 0, sizeof(server));
 
   /*                                                    */
   /* OLD code: Not applicable.                          */
   /*                                                    */
   /* If the len member was not in the original IPv4 code*/
   /* add it now and make sure it is sin6_len for IPv6.  */
   /*                                                    */
   server.sin6_len = sizeof(server);
 
   /*                                                    */
   /* OLD code: memcpy((char *)&server.sin_addr, ...     */
   /* OLD code: server.sin_family = hp->h_addrtype;      */
   /* OLD code: server.sin_port = sp->s_port;            */
   /*                                                    */
   /* Make sure you are using sockaddr_in6 members.      */
   /*                                                    */
   memcpy((char *)&server.sin6_addr, hp->h_addr, hp->h_length);
   server.sin6_family = hp->h_addrtype;
   server.sin6_port = sp->s_port;
 
   /*                                                    */
   /* OLD code: s = socket(AF_INET, SOCK_STREAM, 0);     */
   /*                                                    */
   /* Use the correct address family for IPv6.           */
   /*                                                    */
   s = socket(AF_INET6, SOCK_STREAM, 0);
   if (s < 0) {
    perror("rlogin: socket");
    exit(3);
   }
   ...
   /* Connect does the bind for us */
   if (connect(s, (struct sockaddr *)&server, sizeof(server)) < 0) {
    perror("rlogin: connect");
    exit(5);
   }
   ...
   exit(0);
  }

--------------------------------------------------------------------------------
NOTE: In the assignments to server.sin6_addr and server.sin6_family hp->h_length will always be equal to sizeof(struct in6addr) and hp->h_addrtype will always be equal to AF_INET6.
--------------------------------------------------------------------------------

IPv4 server code ported to IPv6

  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <stdio.h>
  #include <netdb.h>
   ...
  main(argc, argv) /* server side */
   int argc;
   char *argv[];
  {
   int f;
 
   /*                                                    */
   /* OLD code: struct sockaddr_in from;                 */
   /* OLD code: struct sockaddr_in sin;                  */
   /*                                                    */
   /* Change structure to sockaddr_in6 from sockaddr_in. */
   /*                                                    */
   struct sockaddr_in6 from;
   struct sockaddr_in6 sin;
   struct servent *sp;
 
   sp = getservbyname("login", "tcp");
   if (sp == NULL) {
    fprintf(stderr,
     "rlogind: tcp/login: unknown service\n");
    exit(1);
   }
   ...
  #ifndef DEBUG
   /* Disassociate server from controlling terminal. */
   ...
  #endif
 
   memset((char *)&sin, 0, sizeof(sin));
 
   /*                                                    */
   /* OLD code: Not applicable.                          */
   /*                                                    */
   /* If the len member was not in the original IPv4 code*/
   /* add it now and make sure it is sin6_len for IPv6.  */
   /*                                                    */
   sin.sin6_len = sizeof(sin);
 
   /*                                                    */
   /* OLD code: sin.sin_port = sp->s_port;               */
   /*                                                    */
   /* Make sure you are using sockaddr_in6 members.      */
   /*                                                    */
   sin.sin6_port = sp->s_port; /* Restricted port */
 
   /*                                                    */
   /* OLD code: sin.sin_addr.s_addr = INADDR_ANY;        */
   /*                                                    */
   /* Make the modifications for assigning in6addr_any to*/
   /* sin6_addr.                                         */
   /*                                                    */
   sin.sin6_addr = in6addr_any;
   ...
 
   /*                                                    */
   /* OLD code: f = socket(AF_INET, SOCK_STREAM, 0);     */
   /*                                                    */
   /* Use the correct address family for IPv6.           */
   /*                                                    */
   f = socket(AF_INET6, SOCK_STREAM, 0);
   ...
   if (bind(f, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
    ...
   }
   ...
   listen(f, 5);
   for (;;) {
    int g, len = sizeof(from);
 
    g = accept(f, (struct sockaddr *) &from, &len);
    if (g < 0) {
     if (errno != EINTR)
      syslog(LOG_ERR, "rlogind: accept: %m");
     continue;
    }
    if (fork() == 0) {
     close(f);
     doit(g, &from);
    }
    close(g);
   }
   exit(0);
  }

As can be seen in the two IPv6 ported examples, there are only a few changes required to port IPv4 applications to IPv6. You may want to go one step further and use the new getaddrinfo(3N) and getnameinfo(3N) functions to make your IPv6 application more portable. The following examples show how you could modify the client and server examples to use getaddrinfo(3N).
IPv6 client code using getaddrinfo

  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <stdio.h>
  #include <netdb.h>
 
  main(argc, argv) /* client side */
   int argc;
   char *argv[];
  {
   struct addrinfo req, *ans;
   int code, s;
 
   req.ai_flags = 0;
 
   req.ai_family = PF_INET6;               /* Same as AF_INET6.            */
   req.ai_socktype = SOCK_STREAM;
 
   /*                                                    */
   /* Use default protocol (in this case tcp)            */
   /*                                                    */
   req.ai_protocol = 0;
   if ((code = getaddrinfo(argv[1], "login", &req, &ans)) != 0) {
    fprintf(stderr, "rlogin: getaddrinfo failed code %d\n",
     code);
    exit(1);
   }
 
   /*                                                    */
   /* ans must contain at least one addrinfo, use        */
   /* the first.                                         */
   /*                                                    */
   s = socket(ans->ai_family, ans->ai_socktype, ans->ai_protocol);
   if (s < 0) {
    perror("rlogin: socket");
    exit(3);
   }
 
   ...
 
   /* Connect does the bind for us */
   if (connect (s, ans->ai_addr, ans->ai_addrlen) < 0) {
    perror("rlogin: connect");
    exit(5);
   }
 
   ...
 
   /*                                                    */
   /* Free answers after use                             */
   /*                                                    */
   freeaddrinfo(ans);
 
   /* ... */
 
   exit(0);
  }

IPv6 server code using getaddrinfo

  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <stdio.h>
  #include <netdb.h>
 
  main(argc, argv) /* server side */
   int argc;
   char *argv[];
  {
   struct sockaddr_in6 from;
   struct addrinfo req, *ans;
   int code, f, len;
 
   /*                                                                          */
   /* Set ai_flags to AI_PASSIVE to indicate that return     */
   /* address is suitable for bind()                                 */
   /*                                                                            */
   req.ai_flags = AI_PASSIVE;
 
   req.ai_family = PF_INET6;             /* Same as AF_INET6.    */
 
   req.ai_socktype = SOCK_STREAM;
   req.ai_protocol = 0;
 
   if ((code = getaddrinfo(NULL, "login", &req, &ans)) != 0) {
    fprintf(stderr, "rlogind: getaddrinfo failed code %d\n",
     code);
    exit(1);
   }
 
    ...
 
  #ifndef DEBUG
   /* Disassociate server from controlling terminal. */
   ...
  #endif
 
   /*                                                                      */
   /* ans must contain at least one addrinfo, use        */
   /* the first.                                                          */
   /*                                                                       */
   f = socket(ans->ai_family, ans->ai_socktype, ans->ai_protocol);
    ...
 
   if (bind(f, ans->ai_addr, ans->ai_addrlen) < 0) {
     ...
   }
 
   listen(f, 5);
   for (;;) {
    int g, len = sizeof(from);