blob: 86c78b3bb7dccf513630e23c5573e96d3479f8be [file] [log] [blame]
David K. Bainbridge215e0242017-09-05 23:18:24 -07001// Copyright 2013 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// +build ignore
6
7//go:generate go run gen.go
8
9// This program generates internet protocol constants and tables by
10// reading IANA protocol registries.
11package main
12
13import (
14 "bytes"
15 "encoding/xml"
16 "fmt"
17 "go/format"
18 "io"
19 "io/ioutil"
20 "net/http"
21 "os"
22 "strconv"
23 "strings"
24)
25
26var registries = []struct {
27 url string
28 parse func(io.Writer, io.Reader) error
29}{
30 {
31 "http://www.iana.org/assignments/dscp-registry/dscp-registry.xml",
32 parseDSCPRegistry,
33 },
34 {
35 "http://www.iana.org/assignments/ipv4-tos-byte/ipv4-tos-byte.xml",
36 parseTOSTCByte,
37 },
38 {
39 "http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml",
40 parseProtocolNumbers,
41 },
42}
43
44func main() {
45 var bb bytes.Buffer
46 fmt.Fprintf(&bb, "// go generate gen.go\n")
47 fmt.Fprintf(&bb, "// GENERATED BY THE COMMAND ABOVE; DO NOT EDIT\n\n")
48 fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n")
49 fmt.Fprintf(&bb, `package iana // import "golang.org/x/net/internal/iana"`+"\n\n")
50 for _, r := range registries {
51 resp, err := http.Get(r.url)
52 if err != nil {
53 fmt.Fprintln(os.Stderr, err)
54 os.Exit(1)
55 }
56 defer resp.Body.Close()
57 if resp.StatusCode != http.StatusOK {
58 fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url)
59 os.Exit(1)
60 }
61 if err := r.parse(&bb, resp.Body); err != nil {
62 fmt.Fprintln(os.Stderr, err)
63 os.Exit(1)
64 }
65 fmt.Fprintf(&bb, "\n")
66 }
67 b, err := format.Source(bb.Bytes())
68 if err != nil {
69 fmt.Fprintln(os.Stderr, err)
70 os.Exit(1)
71 }
72 if err := ioutil.WriteFile("const.go", b, 0644); err != nil {
73 fmt.Fprintln(os.Stderr, err)
74 os.Exit(1)
75 }
76}
77
78func parseDSCPRegistry(w io.Writer, r io.Reader) error {
79 dec := xml.NewDecoder(r)
80 var dr dscpRegistry
81 if err := dec.Decode(&dr); err != nil {
82 return err
83 }
84 drs := dr.escape()
85 fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated)
86 fmt.Fprintf(w, "const (\n")
87 for _, dr := range drs {
88 fmt.Fprintf(w, "DiffServ%s = %#x", dr.Name, dr.Value)
89 fmt.Fprintf(w, "// %s\n", dr.OrigName)
90 }
91 fmt.Fprintf(w, ")\n")
92 return nil
93}
94
95type dscpRegistry struct {
96 XMLName xml.Name `xml:"registry"`
97 Title string `xml:"title"`
98 Updated string `xml:"updated"`
99 Note string `xml:"note"`
100 RegTitle string `xml:"registry>title"`
101 PoolRecords []struct {
102 Name string `xml:"name"`
103 Space string `xml:"space"`
104 } `xml:"registry>record"`
105 Records []struct {
106 Name string `xml:"name"`
107 Space string `xml:"space"`
108 } `xml:"registry>registry>record"`
109}
110
111type canonDSCPRecord struct {
112 OrigName string
113 Name string
114 Value int
115}
116
117func (drr *dscpRegistry) escape() []canonDSCPRecord {
118 drs := make([]canonDSCPRecord, len(drr.Records))
119 sr := strings.NewReplacer(
120 "+", "",
121 "-", "",
122 "/", "",
123 ".", "",
124 " ", "",
125 )
126 for i, dr := range drr.Records {
127 s := strings.TrimSpace(dr.Name)
128 drs[i].OrigName = s
129 drs[i].Name = sr.Replace(s)
130 n, err := strconv.ParseUint(dr.Space, 2, 8)
131 if err != nil {
132 continue
133 }
134 drs[i].Value = int(n) << 2
135 }
136 return drs
137}
138
139func parseTOSTCByte(w io.Writer, r io.Reader) error {
140 dec := xml.NewDecoder(r)
141 var ttb tosTCByte
142 if err := dec.Decode(&ttb); err != nil {
143 return err
144 }
145 trs := ttb.escape()
146 fmt.Fprintf(w, "// %s, Updated: %s\n", ttb.Title, ttb.Updated)
147 fmt.Fprintf(w, "const (\n")
148 for _, tr := range trs {
149 fmt.Fprintf(w, "%s = %#x", tr.Keyword, tr.Value)
150 fmt.Fprintf(w, "// %s\n", tr.OrigKeyword)
151 }
152 fmt.Fprintf(w, ")\n")
153 return nil
154}
155
156type tosTCByte struct {
157 XMLName xml.Name `xml:"registry"`
158 Title string `xml:"title"`
159 Updated string `xml:"updated"`
160 Note string `xml:"note"`
161 RegTitle string `xml:"registry>title"`
162 Records []struct {
163 Binary string `xml:"binary"`
164 Keyword string `xml:"keyword"`
165 } `xml:"registry>record"`
166}
167
168type canonTOSTCByteRecord struct {
169 OrigKeyword string
170 Keyword string
171 Value int
172}
173
174func (ttb *tosTCByte) escape() []canonTOSTCByteRecord {
175 trs := make([]canonTOSTCByteRecord, len(ttb.Records))
176 sr := strings.NewReplacer(
177 "Capable", "",
178 "(", "",
179 ")", "",
180 "+", "",
181 "-", "",
182 "/", "",
183 ".", "",
184 " ", "",
185 )
186 for i, tr := range ttb.Records {
187 s := strings.TrimSpace(tr.Keyword)
188 trs[i].OrigKeyword = s
189 ss := strings.Split(s, " ")
190 if len(ss) > 1 {
191 trs[i].Keyword = strings.Join(ss[1:], " ")
192 } else {
193 trs[i].Keyword = ss[0]
194 }
195 trs[i].Keyword = sr.Replace(trs[i].Keyword)
196 n, err := strconv.ParseUint(tr.Binary, 2, 8)
197 if err != nil {
198 continue
199 }
200 trs[i].Value = int(n)
201 }
202 return trs
203}
204
205func parseProtocolNumbers(w io.Writer, r io.Reader) error {
206 dec := xml.NewDecoder(r)
207 var pn protocolNumbers
208 if err := dec.Decode(&pn); err != nil {
209 return err
210 }
211 prs := pn.escape()
212 prs = append([]canonProtocolRecord{{
213 Name: "IP",
214 Descr: "IPv4 encapsulation, pseudo protocol number",
215 Value: 0,
216 }}, prs...)
217 fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated)
218 fmt.Fprintf(w, "const (\n")
219 for _, pr := range prs {
220 if pr.Name == "" {
221 continue
222 }
223 fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value)
224 s := pr.Descr
225 if s == "" {
226 s = pr.OrigName
227 }
228 fmt.Fprintf(w, "// %s\n", s)
229 }
230 fmt.Fprintf(w, ")\n")
231 return nil
232}
233
234type protocolNumbers struct {
235 XMLName xml.Name `xml:"registry"`
236 Title string `xml:"title"`
237 Updated string `xml:"updated"`
238 RegTitle string `xml:"registry>title"`
239 Note string `xml:"registry>note"`
240 Records []struct {
241 Value string `xml:"value"`
242 Name string `xml:"name"`
243 Descr string `xml:"description"`
244 } `xml:"registry>record"`
245}
246
247type canonProtocolRecord struct {
248 OrigName string
249 Name string
250 Descr string
251 Value int
252}
253
254func (pn *protocolNumbers) escape() []canonProtocolRecord {
255 prs := make([]canonProtocolRecord, len(pn.Records))
256 sr := strings.NewReplacer(
257 "-in-", "in",
258 "-within-", "within",
259 "-over-", "over",
260 "+", "P",
261 "-", "",
262 "/", "",
263 ".", "",
264 " ", "",
265 )
266 for i, pr := range pn.Records {
267 if strings.Contains(pr.Name, "Deprecated") ||
268 strings.Contains(pr.Name, "deprecated") {
269 continue
270 }
271 prs[i].OrigName = pr.Name
272 s := strings.TrimSpace(pr.Name)
273 switch pr.Name {
274 case "ISIS over IPv4":
275 prs[i].Name = "ISIS"
276 case "manet":
277 prs[i].Name = "MANET"
278 default:
279 prs[i].Name = sr.Replace(s)
280 }
281 ss := strings.Split(pr.Descr, "\n")
282 for i := range ss {
283 ss[i] = strings.TrimSpace(ss[i])
284 }
285 if len(ss) > 1 {
286 prs[i].Descr = strings.Join(ss, " ")
287 } else {
288 prs[i].Descr = ss[0]
289 }
290 prs[i].Value, _ = strconv.Atoi(pr.Value)
291 }
292 return prs
293}