gen.go 8.7 KB

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