github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/net/internal/iana/gen.go (about) 1 // 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 //go:build ignore 6 // +build ignore 7 8 //go:generate go run gen.go 9 10 // This program generates internet protocol constants and tables by 11 // reading IANA protocol registries. 12 package main 13 14 import ( 15 "bytes" 16 "encoding/xml" 17 "fmt" 18 http "github.com/hxx258456/ccgo/gmhttp" 19 "go/format" 20 "io" 21 "io/ioutil" 22 "os" 23 "strconv" 24 "strings" 25 ) 26 27 var registries = []struct { 28 url string 29 parse func(io.Writer, io.Reader) error 30 }{ 31 { 32 "https://www.iana.org/assignments/dscp-registry/dscp-registry.xml", 33 parseDSCPRegistry, 34 }, 35 { 36 "https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml", 37 parseProtocolNumbers, 38 }, 39 { 40 "https://www.iana.org/assignments/address-family-numbers/address-family-numbers.xml", 41 parseAddrFamilyNumbers, 42 }, 43 } 44 45 func main() { 46 var bb bytes.Buffer 47 fmt.Fprintf(&bb, "// go generate gen.go\n") 48 fmt.Fprintf(&bb, "// Code generated by the command above; DO NOT EDIT.\n\n") 49 fmt.Fprintf(&bb, "// Package iana provides protocol number resources managed by the Internet Assigned Numbers Authority (IANA).\n") 50 fmt.Fprintf(&bb, `package iana // import "github.com/hxx258456/ccgo/net/internal/iana"`+"\n\n") 51 for _, r := range registries { 52 resp, err := http.Get(r.url) 53 if err != nil { 54 fmt.Fprintln(os.Stderr, err) 55 os.Exit(1) 56 } 57 defer resp.Body.Close() 58 if resp.StatusCode != http.StatusOK { 59 fmt.Fprintf(os.Stderr, "got HTTP status code %v for %v\n", resp.StatusCode, r.url) 60 os.Exit(1) 61 } 62 if err := r.parse(&bb, resp.Body); err != nil { 63 fmt.Fprintln(os.Stderr, err) 64 os.Exit(1) 65 } 66 fmt.Fprintf(&bb, "\n") 67 } 68 b, err := format.Source(bb.Bytes()) 69 if err != nil { 70 fmt.Fprintln(os.Stderr, err) 71 os.Exit(1) 72 } 73 if err := ioutil.WriteFile("const.go", b, 0644); err != nil { 74 fmt.Fprintln(os.Stderr, err) 75 os.Exit(1) 76 } 77 } 78 79 func parseDSCPRegistry(w io.Writer, r io.Reader) error { 80 dec := xml.NewDecoder(r) 81 var dr dscpRegistry 82 if err := dec.Decode(&dr); err != nil { 83 return err 84 } 85 fmt.Fprintf(w, "// %s, Updated: %s\n", dr.Title, dr.Updated) 86 fmt.Fprintf(w, "const (\n") 87 for _, dr := range dr.escapeDSCP() { 88 fmt.Fprintf(w, "DiffServ%s = %#02x", dr.Name, dr.Value) 89 fmt.Fprintf(w, "// %s\n", dr.OrigName) 90 } 91 for _, er := range dr.escapeECN() { 92 fmt.Fprintf(w, "%s = %#02x", er.Descr, er.Value) 93 fmt.Fprintf(w, "// %s\n", er.OrigDescr) 94 } 95 fmt.Fprintf(w, ")\n") 96 return nil 97 } 98 99 type dscpRegistry struct { 100 XMLName xml.Name `xml:"registry"` 101 Title string `xml:"title"` 102 Updated string `xml:"updated"` 103 Note string `xml:"note"` 104 Registries []struct { 105 Title string `xml:"title"` 106 Registries []struct { 107 Title string `xml:"title"` 108 Records []struct { 109 Name string `xml:"name"` 110 Space string `xml:"space"` 111 } `xml:"record"` 112 } `xml:"registry"` 113 Records []struct { 114 Value string `xml:"value"` 115 Descr string `xml:"description"` 116 } `xml:"record"` 117 } `xml:"registry"` 118 } 119 120 type canonDSCPRecord struct { 121 OrigName string 122 Name string 123 Value int 124 } 125 126 func (drr *dscpRegistry) escapeDSCP() []canonDSCPRecord { 127 var drs []canonDSCPRecord 128 for _, preg := range drr.Registries { 129 if !strings.Contains(preg.Title, "Differentiated Services Field Codepoints") { 130 continue 131 } 132 for _, reg := range preg.Registries { 133 if !strings.Contains(reg.Title, "Pool 1 Codepoints") { 134 continue 135 } 136 drs = make([]canonDSCPRecord, len(reg.Records)) 137 sr := strings.NewReplacer( 138 "+", "", 139 "-", "", 140 "/", "", 141 ".", "", 142 " ", "", 143 ) 144 for i, dr := range reg.Records { 145 s := strings.TrimSpace(dr.Name) 146 drs[i].OrigName = s 147 drs[i].Name = sr.Replace(s) 148 n, err := strconv.ParseUint(dr.Space, 2, 8) 149 if err != nil { 150 continue 151 } 152 drs[i].Value = int(n) << 2 153 } 154 } 155 } 156 return drs 157 } 158 159 type canonECNRecord struct { 160 OrigDescr string 161 Descr string 162 Value int 163 } 164 165 func (drr *dscpRegistry) escapeECN() []canonECNRecord { 166 var ers []canonECNRecord 167 for _, reg := range drr.Registries { 168 if !strings.Contains(reg.Title, "ECN Field") { 169 continue 170 } 171 ers = make([]canonECNRecord, len(reg.Records)) 172 sr := strings.NewReplacer( 173 "Capable", "", 174 "Not-ECT", "", 175 "ECT(1)", "", 176 "ECT(0)", "", 177 "CE", "", 178 "(", "", 179 ")", "", 180 "+", "", 181 "-", "", 182 "/", "", 183 ".", "", 184 " ", "", 185 ) 186 for i, er := range reg.Records { 187 s := strings.TrimSpace(er.Descr) 188 ers[i].OrigDescr = s 189 ss := strings.Split(s, " ") 190 if len(ss) > 1 { 191 ers[i].Descr = strings.Join(ss[1:], " ") 192 } else { 193 ers[i].Descr = ss[0] 194 } 195 ers[i].Descr = sr.Replace(er.Descr) 196 n, err := strconv.ParseUint(er.Value, 2, 8) 197 if err != nil { 198 continue 199 } 200 ers[i].Value = int(n) 201 } 202 } 203 return ers 204 } 205 206 func parseProtocolNumbers(w io.Writer, r io.Reader) error { 207 dec := xml.NewDecoder(r) 208 var pn protocolNumbers 209 if err := dec.Decode(&pn); err != nil { 210 return err 211 } 212 prs := pn.escape() 213 prs = append([]canonProtocolRecord{{ 214 Name: "IP", 215 Descr: "IPv4 encapsulation, pseudo protocol number", 216 Value: 0, 217 }}, prs...) 218 fmt.Fprintf(w, "// %s, Updated: %s\n", pn.Title, pn.Updated) 219 fmt.Fprintf(w, "const (\n") 220 for _, pr := range prs { 221 if pr.Name == "" { 222 continue 223 } 224 fmt.Fprintf(w, "Protocol%s = %d", pr.Name, pr.Value) 225 s := pr.Descr 226 if s == "" { 227 s = pr.OrigName 228 } 229 fmt.Fprintf(w, "// %s\n", s) 230 } 231 fmt.Fprintf(w, ")\n") 232 return nil 233 } 234 235 type protocolNumbers struct { 236 XMLName xml.Name `xml:"registry"` 237 Title string `xml:"title"` 238 Updated string `xml:"updated"` 239 RegTitle string `xml:"registry>title"` 240 Note string `xml:"registry>note"` 241 Records []struct { 242 Value string `xml:"value"` 243 Name string `xml:"name"` 244 Descr string `xml:"description"` 245 } `xml:"registry>record"` 246 } 247 248 type canonProtocolRecord struct { 249 OrigName string 250 Name string 251 Descr string 252 Value int 253 } 254 255 func (pn *protocolNumbers) escape() []canonProtocolRecord { 256 prs := make([]canonProtocolRecord, len(pn.Records)) 257 sr := strings.NewReplacer( 258 "-in-", "in", 259 "-within-", "within", 260 "-over-", "over", 261 "+", "P", 262 "-", "", 263 "/", "", 264 ".", "", 265 " ", "", 266 ) 267 for i, pr := range pn.Records { 268 if strings.Contains(pr.Name, "Deprecated") || 269 strings.Contains(pr.Name, "deprecated") { 270 continue 271 } 272 prs[i].OrigName = pr.Name 273 s := strings.TrimSpace(pr.Name) 274 switch pr.Name { 275 case "ISIS over IPv4": 276 prs[i].Name = "ISIS" 277 case "manet": 278 prs[i].Name = "MANET" 279 default: 280 prs[i].Name = sr.Replace(s) 281 } 282 ss := strings.Split(pr.Descr, "\n") 283 for i := range ss { 284 ss[i] = strings.TrimSpace(ss[i]) 285 } 286 if len(ss) > 1 { 287 prs[i].Descr = strings.Join(ss, " ") 288 } else { 289 prs[i].Descr = ss[0] 290 } 291 prs[i].Value, _ = strconv.Atoi(pr.Value) 292 } 293 return prs 294 } 295 296 func parseAddrFamilyNumbers(w io.Writer, r io.Reader) error { 297 dec := xml.NewDecoder(r) 298 var afn addrFamilylNumbers 299 if err := dec.Decode(&afn); err != nil { 300 return err 301 } 302 afrs := afn.escape() 303 fmt.Fprintf(w, "// %s, Updated: %s\n", afn.Title, afn.Updated) 304 fmt.Fprintf(w, "const (\n") 305 for _, afr := range afrs { 306 if afr.Name == "" { 307 continue 308 } 309 fmt.Fprintf(w, "AddrFamily%s = %d", afr.Name, afr.Value) 310 fmt.Fprintf(w, "// %s\n", afr.Descr) 311 } 312 fmt.Fprintf(w, ")\n") 313 return nil 314 } 315 316 type addrFamilylNumbers struct { 317 XMLName xml.Name `xml:"registry"` 318 Title string `xml:"title"` 319 Updated string `xml:"updated"` 320 RegTitle string `xml:"registry>title"` 321 Note string `xml:"registry>note"` 322 Records []struct { 323 Value string `xml:"value"` 324 Descr string `xml:"description"` 325 } `xml:"registry>record"` 326 } 327 328 type canonAddrFamilyRecord struct { 329 Name string 330 Descr string 331 Value int 332 } 333 334 func (afn *addrFamilylNumbers) escape() []canonAddrFamilyRecord { 335 afrs := make([]canonAddrFamilyRecord, len(afn.Records)) 336 sr := strings.NewReplacer( 337 "IP version 4", "IPv4", 338 "IP version 6", "IPv6", 339 "Identifier", "ID", 340 "-", "", 341 "-", "", 342 "/", "", 343 ".", "", 344 " ", "", 345 ) 346 for i, afr := range afn.Records { 347 if strings.Contains(afr.Descr, "Unassigned") || 348 strings.Contains(afr.Descr, "Reserved") { 349 continue 350 } 351 afrs[i].Descr = afr.Descr 352 s := strings.TrimSpace(afr.Descr) 353 switch s { 354 case "IP (IP version 4)": 355 afrs[i].Name = "IPv4" 356 case "IP6 (IP version 6)": 357 afrs[i].Name = "IPv6" 358 case "AFI for L2VPN information": 359 afrs[i].Name = "L2VPN" 360 case "E.164 with NSAP format subaddress": 361 afrs[i].Name = "E164withSubaddress" 362 case "MT IP: Multi-Topology IP version 4": 363 afrs[i].Name = "MTIPv4" 364 case "MAC/24": 365 afrs[i].Name = "MACFinal24bits" 366 case "MAC/40": 367 afrs[i].Name = "MACFinal40bits" 368 case "IPv6/64": 369 afrs[i].Name = "IPv6Initial64bits" 370 default: 371 n := strings.Index(s, "(") 372 if n > 0 { 373 s = s[:n] 374 } 375 n = strings.Index(s, ":") 376 if n > 0 { 377 s = s[:n] 378 } 379 afrs[i].Name = sr.Replace(s) 380 } 381 afrs[i].Value, _ = strconv.Atoi(afr.Value) 382 } 383 return afrs 384 }