@@ -16,6 +16,10 @@ import (
16
16
"fmt"
17
17
"io"
18
18
"math"
19
+ "os"
20
+ "path"
21
+ "runtime"
22
+ "strconv"
19
23
"time"
20
24
)
21
25
@@ -219,6 +223,7 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
219
223
clientTransactions |
220
224
clientLocalFiles |
221
225
clientPluginAuth |
226
+ clientConnectAttrs |
222
227
mc .flags & clientLongFlag
223
228
224
229
if mc .cfg .clientFoundRows {
@@ -233,7 +238,22 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
233
238
// User Password
234
239
scrambleBuff := scramblePassword (cipher , []byte (mc .cfg .passwd ))
235
240
241
+ attrs := make (map [string ]string )
242
+ attrs ["_os" ] = runtime .GOOS
243
+ attrs ["_client_name" ] = "Go MySQL Driver"
244
+ attrs ["_pid" ] = strconv .Itoa (os .Getpid ())
245
+ attrs ["_platform" ] = runtime .GOARCH
246
+ attrs ["program_name" ] = path .Base (os .Args [0 ])
247
+
248
+ attrlen := 0
249
+ for attrname , attrvalue := range attrs {
250
+ attrlen += len (attrname ) + len (attrvalue )
251
+ // one byte to store attrname length and one byte to store attrvalue length
252
+ attrlen += 2
253
+ }
254
+
236
255
pktLen := 4 + 4 + 1 + 23 + len (mc .cfg .user ) + 1 + 1 + len (scrambleBuff ) + 21 + 1
256
+ pktLen += attrlen + 1 // one byte to store the total length of attrs
237
257
238
258
// To specify a db name
239
259
if n := len (mc .cfg .dbname ); n > 0 {
@@ -301,6 +321,19 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error {
301
321
data [pos ] = 0x00
302
322
pos ++
303
323
}
324
+ pos ++
325
+
326
+ // Connection attributes
327
+ data [pos ] = byte (attrlen )
328
+ pos ++
329
+
330
+ for attrname , attrvalue := range attrs {
331
+ data [pos ] = byte (len (attrname ))
332
+ pos += 1 + copy (data [pos + 1 :], attrname )
333
+
334
+ data [pos ] = byte (len (attrvalue ))
335
+ pos += 1 + copy (data [pos + 1 :], attrvalue )
336
+ }
304
337
305
338
// Assume native client during response
306
339
pos += copy (data [pos :], "mysql_native_password" )
0 commit comments