Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita377ad5

Browse files
committed
I'm including an update to my user defined IP and MAC address type
implementation that's in contrib/ip_and_mac/. This one works rightwith 6.3, avoids the problems I ran into earlier with LIKE, andincludes a bit of extra functionality.From: Tom I Helbekkmo <tih@Hamartun.Priv.NO>
1 parent9336b9b commita377ad5

File tree

8 files changed

+303
-176
lines changed

8 files changed

+303
-176
lines changed

‎contrib/ip_and_mac/Makefile‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
#PostgreSQL type definitions for IP and MAC addresses.
1+
#
2+
#PostgreSQL types for IP and MAC addresses
3+
#
4+
#$Id: Makefile,v 1.2 1998/02/14 17:58:02 scrappy Exp $
25

36
all: ip.so mac.so
47

@@ -17,4 +20,6 @@ mac.o: mac.c mac.h
1720
install: ip.so mac.so
1821
install -c ip.so mac.so /usr/local/pgsql/modules
1922

23+
#
2024
#eof
25+
#

‎contrib/ip_and_mac/README‎

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
PostgreSQL type extensions for IP and MAC addresses.
22
---------------------------------------------------
33

4+
$Id: README,v 1.2 1998/02/14 17:58:03 scrappy Exp $
5+
46
I needed to record IP and MAC level ethernet addresses in a data
57
base, and I really didn't want to store them as plain strings, with
68
no enforced error checking, so I put together the accompanying code
@@ -9,43 +11,46 @@ then thought that this might be useful to others, both directly and
911
as a very simple example of how to do this sort of thing, so here
1012
it is, in the hope that it will be useful.
1113

12-
IP addresses are implemented asan 8 byte struct (this maywell be
14+
IP addresses are implemented asa 6 byte struct (this maybe 1 byte
1315
more than is useful, but I figured that since it has to be at least 5,
14-
it might as well round well) that contains the four bytes of address
15-
and a mask width. Thus, a node address looks like '158.37.96.15/32'
16-
(or just '158.37.96.15', which is understood to mean the same thing).
17-
This address happens to be part of a subnet where I work;
18-
'158.37.96.0/24', which itself is a part of the larger subnet
19-
allocated to our institution, which is '158.37.96.0/21', which again,
20-
if you go by the book, is part of the class "B" net '158.37.0.0/16'.
16+
it might as well be an even number of bytes) that contains the four
17+
byte address and a mask width. The external representation of an IP
18+
address looks like '158.37.96.15/32' (or just '158.37.96.15', which is
19+
understood to mean the same thing). This address happens to be part
20+
of a subnet where I work; '158.37.96.0/24', which itself is a part of
21+
the larger subnet allocated to our site, which is '158.37.96.0/21',
22+
which again, if you go by the old book, is part of the class "B" net
23+
called '158.37.0.0/16'.
2124

2225
Input and output functions are supplied, along with the "normal" <,
23-
<=, =, >=, > and <> operators, which all do what you expect, and the
24-
similarity operator ~~, which checks whether two given addresses are
25-
either the same, or, failing that, whether one is a subnet
26-
specification and the other an address (or a smaller subnet) within
27-
that. Good for picking out records with addresses in a given subnet:
28-
note that '158.37.96.0/21' spans '158.37.96.0' to '158.37.103.255',
29-
which is not all that easily handled in its external representation.
30-
31-
MAC level ethernet addresses are also implemented as an 8 byte struct
32-
(I wish I knew what alignment needs are actually present -- I'm just
33-
not taking any chances here) that contains the address as unsigned
34-
chars. Several input forms are accepted: the following are all the
35-
same address: '08002b:010203', '08002b-010203', '0800.2b01.0203',
36-
'08-00-2b-01-02-03' and '08:00:2b:01:02:03'. Upper and lower case is
37-
accepted for the digits 'a' through 'f'. Output is always in the
38-
latter of the given forms.
39-
40-
Input and output functions are supplied, along with the = and <>
41-
operators, which do what you expect, and the similarity operator ~~,
42-
which checks whether two given addresses belong to hardware from the
43-
same manufacturer (first three bytes the same, that is). As an extra
26+
<=, =, >=, > and <> operators, which all do what you expect. In
27+
addition, there is a function to check whether a given address is a
28+
member of a given subnet: ipaddr_in_net(addr, net), and functions to
29+
return the netmask and the broadcast address of a given network:
30+
ipaddr_mask(net) and ipaddr_bcast(net).
31+
32+
MAC level ethernet addresses are implemented as a 6 byte struct that
33+
contains the address as unsigned chars. Several input forms are
34+
accepted; the following are all the same address: '08002b:010203',
35+
'08002b-010203', '0800.2b01.0203', '08-00-2b-01-02-03' and
36+
'08:00:2b:01:02:03'. Upper and lower case is accepted for the digits
37+
'a' through 'f'. Output is always in the latter of the given forms.
38+
39+
As with IP addresses, input and output functions are supplied as well
40+
as the "normal" operators, which do what you expect. As an extra
4441
feature, a function macaddr_manuf() is defined, which returns the name
45-
of the manufacturer as a string.
42+
of the manufacturer as a string. This is currently held in a
43+
hard-coded struct internal to the C module -- it might be smarter to
44+
put this information into an actual data base table, and look up the
45+
manufacturer there. (Another TODO, for both new data types, is to
46+
interface them to indices. If anyone can explain this to me in a way
47+
that is easier to understand than the current documentation, I would
48+
be most grateful!)
4649

47-
To install: fix the path names in the SQL files and the Makefile if
48-
you need to, then make, make install, slurp the SQL files into psql or
50+
I don't know what changes are needed to the Makefile for other systems
51+
than the one I'm running (NetBSD 1.3), but anyway: to install on a BSD
52+
system: fix the path names in the SQL files and the Makefile if you
53+
need to, then make, make install, slurp the SQL files into psql or
4954
whatever, and you're off. Enjoy!
5055

51-
Bergen, Norway, 1998-01-11, Tom Ivar Helbekkmo (tih@Hamartun.Priv.NO).
56+
Bergen, Norway, 1998-01-31, Tom Ivar Helbekkmo (tih@Hamartun.Priv.NO).

‎contrib/ip_and_mac/ip.c‎

Lines changed: 77 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
/*
22
*PostgreSQL type definitions for IP addresses.
3+
*
4+
*$Id: ip.c,v 1.2 1998/02/14 17:58:03 scrappy Exp $
35
*/
46

57
#include<stdio.h>
@@ -12,13 +14,8 @@
1214
*/
1315

1416
typedefstructipaddr {
15-
unsignedchara;
16-
unsignedcharb;
17-
unsignedcharc;
18-
unsignedchard;
19-
unsignedcharw;
20-
unsignedcharpad1;
21-
shortpad2;
17+
uint32address;
18+
int16width;
2219
}ipaddr;
2320

2421
/*
@@ -35,15 +32,24 @@ bool ipaddr_ge(ipaddr *a1, ipaddr *a2);
3532
boolipaddr_gt(ipaddr*a1,ipaddr*a2);
3633

3734
boolipaddr_ne(ipaddr*a1,ipaddr*a2);
35+
3836
int4ipaddr_cmp(ipaddr*a1,ipaddr*a2);
39-
boolipaddr_like(ipaddr*a1,ipaddr*a2);
37+
38+
boolipaddr_in_net(ipaddr*a1,ipaddr*a2);
39+
ipaddr*ipaddr_mask(ipaddr*a);
40+
ipaddr*ipaddr_bcast(ipaddr*a);
4041

4142
/*
42-
*A utility macro used for sorting addresses numerically:
43+
*Build a mask of a given width:
4344
*/
4445

45-
#defineMag(addr) \
46-
((unsigned long)((addr->a<<24)|(addr->b<<16)|(addr->c<<8)|(addr->d)))
46+
unsigned longbuild_mask(unsignedcharbits) {
47+
unsigned longmask=0;
48+
inti;
49+
for (i=0;i<bits;i++)
50+
mask= (mask >>1) |0x80000000;
51+
returnmask;
52+
}
4753

4854
/*
4955
*IP address reader. Note how the count returned by sscanf()
@@ -79,11 +85,9 @@ ipaddr *ipaddr_in(char *str) {
7985

8086
result= (ipaddr*)palloc(sizeof(ipaddr));
8187

82-
result->a=a;
83-
result->b=b;
84-
result->c=c;
85-
result->d=d;
86-
result->w=w;
88+
result->address= (uint32) ((a<<24)|(b<<16)|(c<<8)|d);
89+
result->address &=build_mask(w);
90+
result->width=w;
8791

8892
return(result);
8993
}
@@ -101,112 +105,112 @@ char *ipaddr_out(ipaddr *addr) {
101105

102106
result= (char*)palloc(32);
103107

104-
if (Mag(addr)>0) {
105-
if (addr->w==32)
108+
if (addr->address>0) {
109+
if (addr->width==32)
106110
sprintf(result,"%d.%d.%d.%d",
107-
addr->a,addr->b,addr->c,addr->d);
111+
(addr->address >>24)&0xff,
112+
(addr->address >>16)&0xff,
113+
(addr->address >>8)&0xff,
114+
addr->address&0xff);
108115
else
109116
sprintf(result,"%d.%d.%d.%d/%d",
110-
addr->a,addr->b,addr->c,addr->d,addr->w);
117+
(addr->address >>24)&0xff,
118+
(addr->address >>16)&0xff,
119+
(addr->address >>8)&0xff,
120+
addr->address&0xff,
121+
addr->width);
111122
}else {
112123
result[0]=0;/* special case for missing address */
113124
}
114125
return(result);
115126
}
116127

117128
/*
118-
*Boolean tests. The Mag() macro was defined above.
129+
*Boolean tests for magnitude.
119130
*/
120131

121132
boolipaddr_lt(ipaddr*a1,ipaddr*a2) {
122-
unsigned longa1mag,a2mag;
123-
a1mag=Mag(a1);
124-
a2mag=Mag(a2);
125-
return (a1mag<a2mag);
133+
return (a1->address<a2->address);
126134
};
127135

128136
boolipaddr_le(ipaddr*a1,ipaddr*a2) {
129-
unsigned longa1mag,a2mag;
130-
a1mag=Mag(a1);
131-
a2mag=Mag(a2);
132-
return (a1mag <=a2mag);
137+
return (a1->address <=a2->address);
133138
};
134139

135140
boolipaddr_eq(ipaddr*a1,ipaddr*a2) {
136-
unsigned longa1mag,a2mag;
137-
a1mag=Mag(a1);
138-
a2mag=Mag(a2);
139-
return ((a1mag==a2mag)&& (a1->w==a2->w));
141+
return (a1->address==a2->address);
140142
};
141143

142144
boolipaddr_ge(ipaddr*a1,ipaddr*a2) {
143-
unsigned longa1mag,a2mag;
144-
a1mag=Mag(a1);
145-
a2mag=Mag(a2);
146-
return (a1mag >=a2mag);
145+
return (a1->address >=a2->address);
147146
};
148147

149148
boolipaddr_gt(ipaddr*a1,ipaddr*a2) {
150-
unsigned longa1mag,a2mag;
151-
a1mag=Mag(a1);
152-
a2mag=Mag(a2);
153-
return (a1mag>a2mag);
149+
return (a1->address>a2->address);
154150
};
155151

156152
boolipaddr_ne(ipaddr*a1,ipaddr*a2) {
157-
unsigned longa1mag,a2mag;
158-
a1mag=Mag(a1);
159-
a2mag=Mag(a2);
160-
return ((a1mag!=a2mag)|| (a1->w!=a2->w));
153+
return (a1->address!=a2->address);
161154
};
162155

163156
/*
164157
*Comparison function for sorting:
165158
*/
166159

167160
int4ipaddr_cmp(ipaddr*a1,ipaddr*a2) {
168-
unsigned longa1mag=Mag(a1),a2mag=Mag(a2);
169-
if (a1mag<a2mag)
161+
if (a1->address<a2->address)
170162
return-1;
171-
elseif (a1mag>a2mag)
163+
elseif (a1->address>a2->address)
172164
return1;
173165
else
174166
return0;
175167
}
176168

177169
/*
178-
*Our "similarity" operator checks whether two addresses are
179-
*either the same node address, or, failing that, whether one
180-
*of them contains the other. This will be true if they have
181-
*the same high bits down as far as the shortest mask reaches.
170+
*Test whether an address is within a given subnet:
182171
*/
183172

184-
unsigned longbuild_mask(unsignedcharbits) {
185-
unsigned longmask=0;
186-
inti;
187-
for (i=0;i<bits;i++)
188-
mask= (mask >>1) |0x80000000;
189-
returnmask;
190-
}
191-
192-
boolipaddr_like(ipaddr*a1,ipaddr*a2) {
193-
unsigned longa1bits,a2bits,maskbits;
194-
if ((a1->w==0)|| (a2->w==0))
173+
boolipaddr_in_net(ipaddr*a1,ipaddr*a2) {
174+
uint32maskbits;
175+
if (a1->width<a2->width)
195176
return FALSE;
196-
if ((a1->w==32)&& (a2->w==32))
177+
if ((a1->width==32)&& (a2->width==32))
197178
returnipaddr_eq(a1,a2);
198-
a1bits=Mag(a1);
199-
a2bits=Mag(a2);
200-
if (a1->w>a2->w) {
201-
maskbits=build_mask(a2->w);
202-
return ((a1bits&maskbits)== (a2bits&maskbits));
203-
}else {
204-
maskbits=build_mask(a1->w);
205-
return ((a2bits&maskbits)== (a1bits&maskbits));
206-
}
179+
maskbits=build_mask(a2->width);
180+
if ((a1->address&maskbits)== (a2->address&maskbits))
181+
return TRUE;
207182
return FALSE;
208183
}
209184

185+
/*
186+
*Pick out just the mask of a network:
187+
*/
188+
189+
ipaddr*ipaddr_mask(ipaddr*a) {
190+
ipaddr*result;
191+
192+
result= (ipaddr*)palloc(sizeof(ipaddr));
193+
result->address=build_mask(a->width);
194+
result->width=32;
195+
196+
returnresult;
197+
}
198+
199+
/*
200+
*Return the broadcast address of a network:
201+
*/
202+
203+
ipaddr*ipaddr_bcast(ipaddr*a) {
204+
ipaddr*result;
205+
206+
result= (ipaddr*)palloc(sizeof(ipaddr));
207+
result->address=a->address;
208+
result->address |= (build_mask(32-a->width) >>a->width);
209+
result->width=32;
210+
211+
returnresult;
212+
}
213+
210214
/*
211215
*eof
212216
*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp